package Niuke;

import com.sun.xml.internal.ws.addressing.WsaTubeHelperImpl;
import jdk.management.resource.internal.inst.FileOutputStreamRMHooks;
import org.omg.CORBA.MARSHAL;
import sun.plugin2.ipc.windows.WindowsIPCFactory;

import java.awt.*;
import java.lang.reflect.Array;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

public class al {
    private static void run() {


    }

    public int GetNumberOfK(int[] array, int k) {
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == k)
                count++;
        }
        return count;
    }

    public int minNumberInRotateArray(int[] array) {
        for (int i = 0; i + 1 < array.length; i++) {
            if (array[i + 1] < array[i])
                return array[i + 1];
        }
        return array[0];
    }

    ArrayList<String> res = new ArrayList<>();
    HashSet<String> set = new HashSet<>();

    public ArrayList<String> Permutation(String str) {
        if (str == null || str.length() == 0) return res;
        char[] chars = str.toCharArray();
        addRes(chars, 0);
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            res.add(iterator.next());
        }
        return res;
    }

    public void addRes(char[] chars, int t) {
        if (t == chars.length - 1) {
            set.add(String.valueOf(chars));
        }
        for (int i = t; i < chars.length; i++) {
            char temp = chars[t];
            chars[t] = chars[i];
            chars[i] = temp;
            addRes(chars, t + 1);
            temp = chars[t];
            chars[t] = chars[i];
            chars[i] = temp;
        }
    }

    public boolean Find(int target, int[][] array) {
        int row = array.length;
        if (row == 0) return false;
        int col = array[0].length;
        if (col == 0) return false;
        int x = col - 1;
        int y = 0;
        while (y < row && x >= 0) {
            int mid = array[y][x];
            if (mid == target) return true;
            if (target > mid) y++;
            if (target < mid) x--;
        }
        return false;
    }

    public int findNthDigit(int n) {
        // write code here
        long start = 1, digit = 1, count = 9;
        while (n > count) {
            n -= count;
            start *= 10;
            digit++;
            count = start * 9 * digit;
        }
        String num = (start + (n - 1) / digit) + "";
        int index = (int) ((n - 1) % digit);
        return Integer.parseInt(num.charAt(index) + "");
    }

    public int duplicate(int[] numbers) {
        // write code here

        if (numbers.length < 2) return -1;
        int min = numbers[0];
        int max = numbers[0];
        for (int i = 0; i < numbers.length; i++) {
            if (min > numbers[i])
                min = numbers[i];
            if (max < numbers[i])
                max = numbers[i];
        }
        int[] res = new int[max - min + 1];
        int bias = min;
        for (int i = 0; i < numbers.length; i++) {
            res[numbers[i] - min]++;
        }
        for (int i = 0; i < res.length; i++) {
            if (res[i] > 1)
                return i + bias;
        }
        return -1;
    }


    HashSet set3 = new HashSet();

    public int duplicate2(int[] numbers) {
        // write code here
        if (numbers.length < 2) return -1;
        for (int i = 0; i < numbers.length; i++) {
            if (!set3.contains(numbers[i])) {
                set3.add(i);
            } else {
                return numbers[i];
            }
        }
        return -1;
    }

    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> res = new ArrayList<>();
        if (k > input.length || k <= 0) return res;
        PriorityQueue<Integer> queue = new PriorityQueue<>((num1, num2) -> num2 - num1);
        for (int i = 0; i < k; i++) {
            queue.offer(input[i]);
        }
        for (int i = k; i < input.length; i++) {
            if (queue.peek() > input[i]) {
                queue.poll();
                queue.offer(input[i]);
            }
        }
        for (int i = 0; i < k; i++) {
            res.add(queue.poll());
        }
        return res;
    }

    public int firstMissingPositive2(int[] nums) {
        Arrays.sort(nums);
        int start = 1;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] >= 1) {
                if (nums[i] != start) return start;
                else start++;
            }
        }
        return -1;
    }

    public int firstMissingPositive(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            while (nums[i] > 0 && nums[i] <= nums.length && nums[nums[i] - 1] != nums[i])
                swap2(nums, nums[i] - 1, i);
        }
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != i + 1)
                return i + 1;
        }
        return nums.length + 1;
    }

    public void swap2(int[] arr, int a1, int a2) {
        int temp = arr[a1];
        arr[a1] = arr[a2];
        arr[a2] = temp;
    }

    int count = 0;

    public int InversePairs(int[] array) {
        if (array.length < 2) return 0;
        MergeSort(array, 0, array.length - 1);
        return count;
    }

    public void MergeSort(int[] arr, int start, int end) {
        int mid = start + (start - end) / 2;
        MergeSort(arr, start, mid);
        MergeSort(arr, mid + 1, end);
        Merge(arr, start, end, mid);
    }

    public void Merge(int[] arr, int start, int end, int mid) {
        if (start == end) return;
        int[] temp = new int[end - start + 1];
        int index = 0;
        int l = start;
        int r = mid + 1;
        while (l <= mid && r <= end) {
            if (arr[l] <= arr[r]) {
                temp[index] = arr[l];
                l++;
                index++;
            } else {
                temp[index] = arr[r];
                r++;
                index++;
                count += mid - l + 1;
                count %= 1000000007;
            }
        }
        while (l <= mid) {
            temp[index] = arr[l];
            l++;
            index++;
        }
        while (r <= end) {
            temp[index] = arr[r];
            r++;
            index++;
        }
        for (int i = start; i <= end; i++) {
            arr[i] = temp[i - start];
        }
    }

    private int cnt = 0;
    private PriorityQueue<Integer> low = new PriorityQueue<>();
    private PriorityQueue<Integer> high = new PriorityQueue<>((num1, num2) -> num2 - num1);

    public void Insert(Integer num) {
        cnt++;
        if (cnt % 2 != 0) {//存到大顶堆
            if (!low.isEmpty() && num > low.peek()) {
                low.offer(num);
                num = low.poll();
            }
            high.offer(num);
        } else {//存到小顶堆
            if (!high.isEmpty() && num < high.peek()) {
                high.offer(num);
                num = high.poll();
            }
            low.offer(num);
        }
    }

    public Double GetMedian() {
        double res = 0;
        if (cnt % 2 != 0) {
            return high.peek() * 1.0;
        } else {
            return (high.peek() + low.peek()) / 2.0;
        }
    }

    String word2 = null;
    StringBuilder sb = new StringBuilder();
    int[][] temp = null;

    public boolean hasPath(char[][] matrix, String word) {
        // write code here
        if (matrix.length == 0 || matrix[0].length == 0) return false;
        word2 = word;
        temp = new int[matrix.length][matrix[0].length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (backtrack(matrix, i, j, 1) == true)
                    return true;
            }
        }
        return false;
    }

    public boolean backtrack(char[][] matrix, int x, int y, int cnt) {
        if (x < matrix.length && x >= 0 && y < matrix[0].length && y >= 0) {
            if (temp[x][y] != 1) {
                sb.append(matrix[x][y]);
                temp[x][y] = 1;
                if (cnt == word2.length()) {
                    if (sb.toString().equals(word2))
                        return true;
                    sb.deleteCharAt(sb.length() - 1);
                    temp[x][y] = 0;
                    return false;
                }
                if (backtrack(matrix, x, y + 1, cnt + 1) ||
                        backtrack(matrix, x, y - 1, cnt + 1) ||
                        backtrack(matrix, x + 1, y, cnt + 1) ||
                        backtrack(matrix, x - 1, y, cnt + 1)) {
                    return true;
                } else {
                    sb.deleteCharAt(sb.length() - 1);
                    temp[x][y] = 0;
                }
            } else
                return false;
        } else
            return false;
        return false;
    }

    public int maxProfit(int[] prices) {
        // write code here
        int len = prices.length;
        if (len < 2) return 0;
        int[][] res = new int[len][2];
        res[0][0] = 0;
        res[0][1] = -prices[0];
        for (int i = 1; i < prices.length; i++) {
            res[i][0] = Math.max(res[i - 1][0], res[i - 1][1] + prices[i]);
            res[i][1] = Math.max(-prices[i], res[i - 1][1]);
        }
        return res[prices.length - 1][0];
    }

    public int FindGreatestSumOfSubArray(int[] array) {
        if (array.length == 1) return array[0];
        int[] res = new int[array.length];
        res[0] = array[0];
        int max = res[0];
        for (int i = 1; i < array.length; i++) {
            res[i] = Math.max(res[i - 1] + array[i], array[i]);
            max = Math.max(max, res[i]);
        }
        return max;
    }


    public int jumpFloorII(int target) {
        if (target == 0 || target == 1) return 1;
        int res = 1;
        for (int i = 2; i <= target; i++) {
            res <<= 2;
        }
        return res;
    }

    public int[] FindGreatestSumOfSubArray2(int[] array) {
        // write code here
        if (array.length == 1) return array;
        int start = 0;
        int end = 0;
        int temp = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] > array[i] + temp) {
                start = i;
            } else {

            }
        }
        return null;
    }

    public int maxValue(int[][] grid) {
        // write code here
        int m = grid.length;
        int n = grid[0].length;
        int[][] res = new int[m][n];
        res[0][0] = grid[0][0];
        for (int i = 1; i < m; i++) {
            res[i][0] = res[i - 1][0] + res[i][0];
        }
        for (int j = 1; j < n; j++) {
            res[0][j] = res[0][j - 1] + res[0][j];
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                res[m][n] = Math.max(res[m - 1][n], res[m][n - 1]) + grid[m][n];
            }
        }
        return res[m - 1][n - 1];
    }

    public int lengthOfLongestSubstring(String s) {
        // write code here
        if (s.length() == 0 && s.equals(" ")) return 0;
        int currentLen = 0;
        int maxLen = 0;
        char[] chars = s.toCharArray();
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < chars.length; i++) {
            if (map.containsKey(chars[i])){
                int d=i-map.get(chars[i]);
                if (d>currentLen)
                    currentLen++;
                else
                    currentLen=d;
            }else {
                currentLen++;
            }
            if (currentLen>maxLen)
                maxLen=currentLen;
            map.put(chars[i],i);
        }
        return maxLen;
    }

    public int rectCover(int target) {
        int[] dp=new int[target+1];
        dp[1]=1;
        dp[2]=2;
        for (int i=3;i<target+1;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[target];
     }

    public int[] FindGreatestSumOfSubArray3 (int[] array) {
        // write code here
        if (array.length==1) return array;
        int temp=array[0];
        int max=array[0];
        int index=1;
        int len=1;
        int maxlen=1;
        for (int i=1;i<array.length;i++){
            int temp1=temp;
            temp=Math.max(temp+array[i],array[i]);
            if (temp1+array[i]>=array[i]){
                len++;
            }else {
                len=1;
            }
            if (temp>max||(temp==max&&len>maxlen)){
                index=i;
                maxlen=len;
                max=temp;
            }
        }
        return Arrays.copyOfRange(array,index-maxlen+1,index+1);
    }

    public int solve2(String nums) {
        // write code here
        if (nums.length()==0||nums.equals(" ")||nums.charAt(0)=='0') return 0;
        char[] chars = nums.toCharArray();
        int[] dp=new int[chars.length+1];
        dp[0]=1;
        dp[1]=1;
        for (int i=2;i<=chars.length;i++){
            if (chars[i-1]!='0'){
                dp[i]+=dp[i-1];
            }
            int temp=(chars[i-2]-'0')*10+(chars[i-1]-'0');
            if (10<=temp&&temp<=26)
                dp[i]+=dp[i-2];
        }
        return dp[chars.length];
    }

    public int Add(int num1,int num2) {
        while (num2!=0){
            int temp=num1^num2;
            num2=(num1&num2)<<1;
            num1=temp;
        }
        return num1;
    }

    public double Power(double base, int exponent) {
            if(exponent==0) return 1.0;
            if (exponent<0){
                base=1/base;
                exponent=-exponent;
            }
            double res=Power(base,exponent/2);
            if ((exponent&1)==1){
                res=res*res*base;
            }else {
                res*=res;
            }
            return res;
    }

    ArrayList<Integer> list=new ArrayList<>();
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        if (matrix.length==0||matrix[0].length==0) return list;
        process(matrix,0,0,matrix.length-1,matrix[0].length-1);
        return list;
    }
    public void process(int[][] matrix,int x1,int y1,int x2,int y2){
        if (x1==x2&&y1==y2) {
            list.add(matrix[x1][y1]);
            return;
        }
        if (x1==x2)
            for (int i=y1;i<=y2;i++)
                list.add(matrix[x1][i]);
        if (y1==y2)
            for (int i=x1;i<=x2;i++)
                list.add(matrix[i][y1]);
        if (x1>x2||y1>y2) return;
        for (int i=y1;i<y2;i++)
            list.add(matrix[x1][i]);
        for (int i=x1;i<x2;i++)
            list.add(matrix[i][y2]);
        for (int i=y2;i>y1;i--)
            list.add(matrix[x2][i]);
        for (int i=x2;i>x1;i--)
            list.add(matrix[i][y1]);
        process(matrix,x1+1,y1+1,x2-1,y2-1);
    }

    public boolean IsContinuous(int [] numbers) {
            Arrays.sort(numbers);
            for (int i=4;i>0;i--){
                if (numbers[i]==numbers[i-1]&&numbers[i]!=0)
                    return false;
            }
            int temp=0;
            for (int i=3;i>=0;i--){
                if (numbers[i]==0)
                    temp-=1;
                else
                    temp=temp+numbers[i+1]-numbers[i]-1;
            }
            return temp==0?true:false;
    }



    private String ret=null;
    private int[] num;
    public String PrintMinNumber2(int [] numbers) {
            if (numbers.length==0||numbers==null) return " ";
            num=numbers;
            ret="9999999999999999999999999";
            dfs(0);
            return ret;
    }
    public void dfs(int t){
        if (t==num.length){
            StringBuilder sb=new StringBuilder();
            for (int i=0;i<num.length;i++){
                sb.append(num[i]);
            }
            if (sb.toString().compareTo(ret)<0)
                ret=sb.toString();
            return;
        }
        for (int i=t;i<num.length;i++){
            swap(t,i);
            dfs(t+1);
            swap(t,i);
        }
    }
    public void swap(int x,int y){
        int temp=num[x];
        num[x]=num[y];
        num[y]=temp;
    }


    public String PrintMinNumber(int [] numbers) {
        if (numbers.length==0||numbers==null) return " ";
        String[] sarr=new String[numbers.length];
        for (int i=0;i<numbers.length;i++){
            sarr[i]=numbers[i]+" ";
        }
        Arrays.sort(sarr,(i1,i2)->{
            return (i1+" "+i2).compareTo(i2+""+i1);
        });
        StringBuilder sb=new StringBuilder();
        for (String s:sarr)
            sb.append(s);
        return sb.toString();
    }

    public int GetUglyNumber_Solution(int index) {
        if(index<6)
            return index;
        int p2=0;
        int p3=0;
        int p5=0;
        int[] res=new int[index];
        res[0]=1;
        int idx=1;
        while (index>1){
            res[idx]=Math.min(res[p2]*2,Math.min(res[p3]*3,res[p5]*5));
            if (res[idx]==res[p2]*2)
                p2++;
            if (res[idx]==res[p3]*3)
                p3++;
            if (res[idx]==res[p5]*5)
                p5++;
            idx++;
        }
        return res[index-1];
    }

    private ArrayList<Integer> res2=new ArrayList<>();
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        int right=array.length;
        int left=0;
        while (left<right){
            int temp=array[left]+array[right];
            if (temp==sum){
                res2.add(array[left]);
                res2.add(array[right]);
                return res2;
            }
            if (temp<sum)
                left++;
            else
                right--;
        }
        return res2;

    }

    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer> > res=new ArrayList<>();
        if (sum<3)
            return res;
        int left=1;
        int right=2;
        while (right>left){
            int temp=(right-left+1)*(right+left)/2;
            if (temp==sum){
                ArrayList<Integer> r=new ArrayList<>();
                for (int i=left;i<=right;i++){
                    r.add(i);
                }
                res.add(r);
            }else if (temp<sum){
                left++;
            }else
                right--;
        }
        return res;
    }

    public String LeftRotateString(String str,int n) {
        char[] chars = str.toCharArray();
        char[] res=new char[chars.length];
        int right_n=chars.length-n%chars.length;
        for (int i=0;i<res.length;i++){
            res[(i+right_n)%res.length]=chars[i];
        }
        StringBuilder sb=new StringBuilder();
        for (int i=0;i<res.length;i++)
            sb.append(res[i]);
        return sb.toString();
    }

    public int LastRemaining_Solution2(int n, int m) {
            if (n==1) return 0;
            int x=LastRemaining_Solution(n-1,m);
            return (x+m)%n;
    }

    public int LastRemaining_Solution(int n, int m) {
        int[] dp=new int[n+1];
        dp[1]=0;
        for (int i=0;i<=n;i++){
            dp[i]=(dp[i-1]+m)%n;
        }
        return dp[n];
    }

    Queue<Character> queue=new LinkedList<>();
    HashMap<Character,Integer> map=new HashMap<>();
    public void Insert(char ch)
    {
        if (!map.containsKey(ch)){
            queue.offer(ch);
            map.put(ch,1);
        }else {
            map.put(ch,2);
        }
    }
    //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {
            while (!queue.isEmpty()){
                Character peek = queue.peek();
                if (map.get(peek)==1)
                    return peek;
                else
                    queue.poll();
            }
            return '#';
    }


    public int cutRope(int target) {
        if (target==2) return 1;
        if (target==3) return 2;
        if (target==4) return 4;
        return process3(target);
    }

    public int process3(int target){
        int[] dp=new int[target+1];
        dp[1]=1;
        dp[2]=2;
        dp[3]=3;
        dp[4]=4;
        for (int i=5;i<=target;i++){
            for (int j=1;j<i;j++){
                dp[i]=Math.max(dp[i],i*dp[i-j]*j);
            }
        }
        return dp[target];
    }

    public long cutRope (long number) {
        // write code here
        if (number==2) return 1;
        if (number==3) return 2;
        if (number==4) return 4;
        long res=1;
        long left=number%3;
        long count=(number-left)/3;
        if (left==1)
            count--;
        for(long i=1;i<=count;i++){
            res*=3;
        }
        return left==1?count*4:count*6;
    }

    public static class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode ReverseList(ListNode head) {
            if (head==null) return null;
            if (head.next==null) return head;
            ListNode t=head.next;
            ListNode listNode = ReverseList(t);
            t.next=head;
            return listNode;
    }

    public static ListNode reverseBetween (ListNode head, int m, int n) {
        ListNode pre=null;
        ListNode cur=head;
        int index=1;
        while (index<m){
            pre=cur;
            cur=cur.next;
            index++;
        }
        ListNode t1=pre;
        ListNode t2=cur;
        if (pre==null)
            pre=cur;
        else
            pre=pre.next;
        cur=cur.next;
        index++;
        while (index<=n){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
            index++;
        }
        if (t1!=null){
            t1.next = pre;
            t2.next=cur;
            return head;
        }else{
            t2.next=cur;
            return pre;
        }
    }

    public int findPeakElement (int[] nums) {
        // write code here
        if (nums.length==1) return 0;
        if (nums[0]>nums[1]) return 0;
        if (nums[nums.length-1]>nums[nums.length-2]) return nums.length-1;
        int left=0;
        int right=nums.length-1;
        while (left<right){
            int mid=left+((right-left)>>1);
            if (nums[mid-1]<nums[mid]&&nums[mid]>nums[mid+1])
                return mid;
            else if (nums[mid]<nums[mid+1])
                left=mid+1;
            else if(nums[mid]>nums[mid+1])
                right=mid-1;

        }
        return left;
    }

    public int search (int[] nums, int target) {
        // write code here
        int left=0;
        int right=nums.length;
        while (left<right){
            int mid=left+((right-left)>>1);
            if (nums[mid]==target)
                return mid;
            else if (nums[mid]>target)
                right=mid-1;
            else
                left=mid+1;
        }
        return -1;
    }

    public ListNode removeNthFromEnd (ListNode head, int n) {
        // write code here
        ListNode pre=null;
        ListNode cur=head;
        ListNode t=head;
        while (n>0){
            t=t.next;
        }
        if (t==null)
            return head.next;
        while (t!=null){
            t=t.next;
            pre=cur;
            cur=cur.next;
        }
        pre.next=cur.next;
        return head;
    }

    public int compare (String version1, String version2) {
        // write code here
        int len1=version1.length();
        int len2=version2.length();
        int x1=0;
        int y1=0;
        while (x1<len1||y1<len2){
            int temp1=0;
            int temp2=0;
            while (x1<len1&&version1.charAt(x1)!='.'){
                temp1=temp1*10+(version1.charAt(x1)-'0');
                x1++;
            }
            while (y1<len2&&version2.charAt(y1)!='.'){
                temp2=temp2*10+(version1.charAt(y1)-'0');
                y1++;
            }
            if (temp1>temp2)
                return 1;
            else if (temp1<temp2)
                return -1;
            x1++;
            y1++;

        }
        return 0;
    }

    public int InversePairs2(int [] array) {
        if (array.length==0||array.length==1) return 0;
        return process(array,0,array.length-1);
    }

    public int process(int[]arr,int l,int r){
        if (l==r)
            return 0;
        int mid=l+((r-l)>>1);
        return process(arr,l,mid)+
                process(arr,mid+1,r)+
                merge(arr,l,mid,r);
    }

    public int merge(int[] arr,int l,int mid,int r){
        int[] temp=new int[r-l+1];
        int left=l;
        int right=mid+1;
        int res=0;
        int i=0;

        while (left<=mid&&right<=r){
            if (arr[left]>arr[right]) {
                res += mid - left + 1;
                res %= 1000000007;
                temp[i++]=arr[right++];
            }else {
                temp[i++]=arr[left++];
            }
            /*if(arr[left]>arr[right]){
                res+=mid-left+1;
                res%=1000000007;
            }
            temp[i++]=(arr[left]>arr[right]?arr[right++]:arr[left++]);*/
        }

        while (left<=mid)
            temp[i++]=arr[left++];
        while (right<=r)
            temp[i++]=arr[right++];

        for (int j=0;j<temp.length;j++)
            arr[j+l]=temp[j];

        return res%1000000007;

    }

    public ArrayList<ArrayList<Integer>> levelOrder2(TreeNode root) {
        // write code here
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if (root==null) return res;
        LinkedList<TreeNode> queue=new LinkedList<>();
        queue.push(root);
        while (!queue.isEmpty()){
            int size = queue.size();
            ArrayList<Integer> temp=new ArrayList<>();
            while (size>0){
                TreeNode poll = queue.poll();
                //temp.add(poll.val);
                size--;
               // if (poll.left!=null)
               //     queue.push(poll.left);
                // (poll.right!=null)
                //    queue.push(poll.right);
            }
            res.add(temp);
        }
        return res;
    }

    public boolean isPail (ListNode head) {
        // write code here
        if (head==null||head.next==null)
            return true;
        ListNode n1=head;
        ListNode n2=head;

        while (n2.next!=null&&n2.next.next!=null){
            n1=n1.next;
            n2=n2.next.next;
        }
        ListNode cur=n1.next;
        n1.next=null;
        ListNode pre=null;
        while (cur!=null){
            ListNode temp=cur.next;
            cur.next=pre;
            pre=cur;
            cur=temp;
        }

        while (pre!=null&&head!=null){
            if (pre.val!=head.val)
                return false;
            pre=pre.next;
            head=head.next;
        }
        return true;

    }

    public ListNode oddEvenList (ListNode head) {
        // write code here
        if (head==null||head.next==null) return null;
        ListNode o1=null;
        ListNode o2=null;
        ListNode j1=null;
        ListNode j2=null;
        while (head!=null){
            if (((head.val)&1)==0){
                if (j2==null){
                    o1=head;
                    o2=head;
                }else {
                    o2.next=head;
                }
            }else {
                if (j1==null){
                    j1=head;
                    j2=head;
                }else {
                    j2.next=head;
                }
            }
        }
        if (j2!=null){
            j2.next=o1;
            return j1;
        }else {
            return o1;
        }
    }

    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        if (head==null||head.next==null) return head;

        //len
        int len=0;
        ListNode t=head;
        while (t!=null){
            t=t.next;
            len++;
        }

        int count=len/k;
        ListNode pre=null;
        ListNode cur=head;
        ListNode nHead=null;
        ListNode p=null;
        for (int i=0;i<count;i++){
            int t_k=k;
            ListNode next=null;
            ListNode temp=null;
            while (t_k>0){
                if (t_k==k)
                    temp=cur;
                next=cur.next;
                cur.next=pre;
                pre=cur;
                cur=next;
                t_k--;
            }
            temp.next=next;
            cur=next;
            pre=temp;
            if (nHead==null) {
                nHead = cur;
                p=temp;
            }else {
                p.next=pre;
                p=pre;
            }

        }
        return head;

    }

    /*public int[] sortArray2(int[] nums) {
        if(nums==null||nums.length<2)
            return nums;
        for (int i=0;i<nums.length;i++)
            HeapInsert(nums,i);
        int len=nums.length;
        swap(nums,0,len-1);
        while (len>0){
            HeapAdjust(nums,0,len);
            swap(nums,0,len);
            len--;
        }
        return nums;
    }

    public void HeapInsert(int[] nums,int index){
        while (nums[index]>nums[(index/2)-1]){
            swap(nums,index,(index/2)-1);
            index=(index/2)-1;
        }
    }

    public void HeapAdjust(int[] nums,int index,int heapSize){
        int left=index*2+1;
        while (left<heapSize){
            int index_biggest=((left+1<heapSize)&&(nums[left+1]>nums[left]))?
                                left+1:left;
            index_biggest=nums[left]>nums[index_biggest]?left:index_biggest;
            if (index_biggest==left)
                break;
            else
                swap(nums,index_biggest,left);
            index=index_biggest;
            left=index_biggest*2+1;
        }
    }
    public void swap(int[] arr,int index1,int index2){
        int temp=arr[index1]^arr[index2];
        arr[index1]=temp^arr[index1];
        arr[index2]=temp^arr[index2];
    }

    public int[] sortArray(int[] nums) {
        if(nums==null||nums.length<2)
            return nums;
        quickSort(nums,0,nums.length-1);
        return nums;
    }
    public void quickSort(int[] nums,int i,int j){
        if (i<j){
            int random=(int)(i+Math.random()*(j-i+1));
            swap(nums,random,j);
            int[] paration = paration(nums, i, j);
            quickSort(nums,i,paration[0]-1);
            quickSort(nums,paration[1]+1,j);
        }
    }
    public int[] paration(int[] arr,int i,int j){
        int less=i-1;
        int more=j;
        while (less<more){
            if (arr[i]<arr[j])
                swap(arr,++less,j++);
            else if (arr[i]>arr[j])
                swap(arr,--more,j);
            else
                j++;
        }
        swap(arr,more,j);
        return new int[]{less+1,more};
    }*/


    public int findKthLargest_init(int[] nums, int k) {
        int len=nums.length;
        return quickSort(nums,0,len-1,k);
    }


    public int quickSort(int[] arr,int l,int r,int k){
        if(r-l+1<k) return 0;
        int random_index=l+(int)((r-l+1)*Math.random());
        swap(arr,random_index,r);
        int partation=partation(arr,l,r);
        int gap=partation-l+1;
        if(gap==k)
            return arr[partation];
        else if(gap<k)
            return quickSort(arr,partation+1,r,k-gap);
        else
            return quickSort(arr,l,partation-1,k);
    }

    public int partation(int[] arr,int l,int r){
        int bound=l-1;
        int i=l;
        while(i<r){
            if(arr[i]<arr[r]){
                if(i!=bound)
                    swap(arr,++bound,i++);
            }else
                i++;
        }
        swap(arr,++bound,r);
        return bound;
    }

    public void swap(int[] arr,int a,int b){
        int temp=arr[a]^arr[b];
        arr[a]=temp^arr[a];
        arr[b]=temp^arr[b];
    }

    public String longestPalindrome(String s) {
        int length = s.length();
        if (length==1) return s;
        char[] chars = process(s);
        int[] lenarr=new int[chars.length];
        int c=-1;
        int r=-1;
        int max=Integer.MIN_VALUE;
        int max_index=-1;
        for (int i=0;i!=chars.length;i++){
            lenarr[i]=r>i?Math.min(r-i,lenarr[2*c-i]):1;
            while (i+lenarr[i]<chars.length&&i-lenarr[i]>-1){
                if (chars[i+lenarr[i]]==chars[i-lenarr[i]])
                    lenarr[i]++;
                else
                    break;
            }
            if (lenarr[i]+i>r){
                r=lenarr[i]+i;
                c=i;
            }
            if (lenarr[i]>max){
                max=lenarr[i];
                max_index=i;
            }

        }

        int temp=lenarr[max_index]-1;
        StringBuilder sb=new StringBuilder();
        for (int i=max_index-temp;i<=max_index+temp;i++){
            if (lenarr[i]!='#')
                sb.append(lenarr[i]);
        }

        return sb.toString();

    }

    public char[] process(String s){
        char[] chars = s.toCharArray();
        char[] res=new char[chars.length*2+1];
        int index=0;
        for (int i=0;i<res.length;i++)
            res[i]=(i&1)==0?'#':chars[index++];
        return res;
    }

    public ListNode detectCycle(ListNode head) {
        if (head==null||head.next==null||head.next.next==null) return null;
        ListNode slow=head.next;
        ListNode fast=head.next.next;
        if (fast==null) return null;
        while (slow!=fast){
            if (slow.next==null||fast.next==null||fast.next.next==null) return null;
            slow=slow.next;
            fast=fast.next.next;
        }
        if (fast.next==null)
            return null;
        slow=head;
        while (slow!=fast){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }

    public ListNode getKthFromEnd(ListNode head, int k) {
        if (head==null||k==0) return null;
        ListNode a=head;
        ListNode b=head;
        while (k>0){
            if (b.next==null)
                return null;
            else
                b=b.next;
            k--;
        }
        while (b!=null){
            a=a.next;
            b=b.next;
        }
        return a;
    }

    public int[] exchange(int[] nums) {
            int left=0;
            int right=nums.length;
            while (left<right){
                while (left<right&&((nums[left]&1)==1)) left++;
                while (right>left&&((nums[right]&1)==0)) right--;
                if (left<right){
                    int temp=nums[left]^nums[right];
                    nums[left]=temp^nums[left];
                    nums[right]=temp^nums[right];
                }
                else
                    break;
            }
            return nums;
    }

    public boolean isMatch2(String s, String p) {
        int n=s.length();
        int m=p.length();
        boolean[][] dp=new boolean[n+1][m+1];
        for (int i=0;i<=n;i++){
            for (int j=0;j<=m;j++) {
                if (j == 0)
                    dp[i][j] = (i == 0);
                else {
                    if (p.charAt(j-1)!='*'){
                        if (i>0&&((s.charAt(i-1)==p.charAt(j-1))||p.charAt(j-1)=='.'))
                            dp[i][j]=dp[i-1][j-1];
                    }else {
                        if (j>=2)
                            dp[i][j]|=dp[i][j-2];
                        if (i>=1&&j>=2&&((s.charAt(i-1)==p.charAt(j-2))||p.charAt(j-2)=='.'))
                            dp[i][j]|=dp[i-1][j];
                    }
                }

            }
        }
        return dp[n][m];


    }


    public boolean exist(char[][] board, String word) {
        if(board==null||board.length<1||board[0].length<1||word==null||word.equals(""))
            return false;
        int m= board.length;
        int n=board[0].length;
        int[][] visitd=new int[m][n];
        for (int i=0;i<m;i++){
            for (int j=0;j<n;j++){
                if (hashPath(board,visitd,0,word,i,j))
                    return true;
            }
        }
        return false;
    }
    public boolean hashPath(char[][] board,int[][] visited,int index,String word,int i,int j){
        if (i<0||i>=board.length||j<0||j>=board[0].length||visited[i][j]==1||board[i][j]!=word.charAt(index))
            return false;
        if (index==word.length()-1)
            return true;
        visited[i][j]=1;
        boolean haspath=false;
        haspath=hashPath(board, visited, index+1, word, i-1, j)|
                hashPath(board, visited, index+1, word, i+1, j)|
                hashPath(board, visited, index+1, word, i, j-1)|
                hashPath(board, visited, index+1, word, i, j+1);
        visited[i][j]=0;
        return haspath;
    }



    private int count_=0;
    private int k_=0;
    public int movingCount(int m, int n, int k) {
        k_=k;
        int i=0;
        int j=0;
        int[][] flags=new int[m][n];
        move(0,0,flags,m,n);
        return count_;
    }
    public void move(int i,int j,int[][] flags,int m,int n){
        if (i<0||i>m-1||j<0||j>n-1||flags[i][j]==1||i+j<k_)
            return;
        count_++;
        flags[i][j]=1;
        move(i+1,j,flags,m,n);
        move(i-1,j,flags,m,n);
        move(i,j+1,flags,m,n);
        move(i,j-1,flags,m,n);
        flags[i][j]=0;
    }

    /*public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(B==null) return false;
        if (A==null) return false;
        return theSame(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B);
    }

    public boolean theSame(TreeNode a, TreeNode b){
        if (b==null)
            return true;
        if (a==null)
            return false;
        if (a.val!=b.val)
            return false;
        return theSame(a.left,b.left)&&theSame(a.right,b.right);
    }*/

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
            if (list1==null)
                return list2;
            if (list2==null)
                return list1;
            ListNode res=null;
            if (list1.val< list2.val){
                res=list1;
                res.next=mergeTwoLists(list1.next,list2);
            }else {
                res=list2;
                res.next=mergeTwoLists(list1,list2.next);
            }

            return res;

    }

    /*public boolean isSymmetric(TreeNode root) {
        return isSame(root,root);
    }

    public boolean isSame(TreeNode node1,TreeNode node2){
        if(node1==null&&node2==null)
            return true;
        if (node1==null&&node2!=null)
            return false;
        if (node2==null&&node1!=null)
            return false;
        if (node1.val!=node2.val)
            return false;
        return isSame(node1.left,node2.right)&&isSame(node1.right,node2.left);
    }*/

    /*public List<List<Integer>> levelOrder(TreeNode root) {
            if (root==null) return new ArrayList<>();
            List<List<Integer>> res=new ArrayList<>();
            Queue<TreeNode> queue=new LinkedList<>();
            queue.add(root);
            int cur=1;
            int next=0;

            List<Integer> temp=new ArrayList<>();
            while (!queue.isEmpty()){
                TreeNode poll = queue.poll();
                cur--;
                temp.add(poll.val);
                if (poll.left!=null){
                    queue.offer(poll.left);
                    next++;
                }
                if (poll.right!=null){
                    queue.offer(poll.right);
                    next++;
                }
                if (cur==0){
                    res.add(temp);
                    temp=new ArrayList<>();
                    cur=next;
                    next=0;
                }
            }
            return res;

    }*/

    public boolean validateStackSequences(int[] pushed, int[] popped) {
            if (pushed.length==0&&popped.length==0) return true;
            int i=0;
            int j=0;
            Stack<Integer> stack=new Stack<>();
            while (i< pushed.length){
                stack.push(pushed[i++]);
                while (j<popped.length&&stack.peek()==popped[j]){
                    stack.pop();
                    j++;
                }
            }
            return stack.isEmpty();
    }

    public ListNode addInList (ListNode head1, ListNode head2) {
        // write code here
        if (head1==null&&head2==null) return null;
        if (head1==null&&head2!=null) return head2;
        if (head2==null&&head1!=null) return head1;

        ListNode heada = reverse(head1);
        ListNode headb = reverse(head2);
        ListNode index1=heada;
        ListNode index2=headb;
        ListNode res=index1.val+index2.val>9?new ListNode(0):new ListNode(index1.val+index2.val);
        int add=res.val==0?1:0;
        ListNode p=res;
        index1=index1.next;
        index2=index2.next;
        while (index1!=null&&index2!=null){
            p.next=index1.val+index2.val+add>9?new ListNode(index1.val+index2.val+add-10):new ListNode(index1.val+index2.val+add);
            add= index1.val+index2.val+add>9?1:0;
            p=p.next;
            index1=index1.next;
            index2=index2.next;
        }
        while (index1!=null){
            p.next=index1.val+add>9?new ListNode(index1.val+add-10):new ListNode(index1.val+add);
            add=index1.val+add>9?1:0;
            p=p.next;
            index1=index1.next;
        }
        while (index2!=null){
            p.next=index2.val+add>9?new ListNode(index2.val+add-10):new ListNode(index2.val+add);
            add=index2.val+add>9?1:0;
            p=p.next;
            index2=index2.next;
        }
        if (add!=0)
            p.next=new ListNode(add);
        return reverse(res);
    }

    public ListNode reverse(ListNode node){
        if (node==null||node.next==null)
            return node;
        ListNode next=node.next;
        ListNode reverse = reverse(node.next);
        next.next=node;
        node.next=null;
        return reverse;
    }


    public ListNode sortInList2 (ListNode head) {
        // write code here
        PriorityQueue<ListNode> queue=new PriorityQueue<>(Comparator.comparingInt(node -> node.val));
        ListNode p=head;
        while (p!=null){
            queue.add(p);
            p=p.next;
        }
        ListNode res=new ListNode(-1);
        ListNode temp=res;
        while (!queue.isEmpty()){
            ListNode poll = queue.poll();
            temp.next=poll;
            temp=temp.next;
        }
        temp.next=null;
        return res.next;

    }

    public ListNode sortInList (ListNode head) {
        // write code here
        if (head==null||head.next==null)
            return head;
        ListNode left=head;
        ListNode mid=head.next;
        ListNode right=head.next.next;
        while (right!=null&&right.next!=null){
            left=left.next;
            mid=mid.next;
            right=right.next.next;
        }
        left.next=null;
        return MergeList(sortInList(head),sortInList(mid));
    }

    private ListNode MergeList(ListNode l1, ListNode l2) {
        if (l1==null)
            return l2;
        if (l2==null)
            return l1;
        ListNode res=new ListNode(-1);
        ListNode p=res;
        while (l1!=null&&l2!=null){
            if (l1.val<l2.val){
                p.next=l1;
                l1=l1.next;
            }else {
                p.next=l2;
                l2=l2.next;
            }
            p=p.next;
        }
        if (l1!=null)
            p.next=l1;
        if(l2!=null)
            p.next=l2;
        return res.next;
    }

        public int maxLength (int[] arr) {
            // write code here
            if (arr.length==0) return 0;
            int j=0;
            int maxlen=Integer.MIN_VALUE;
            int curlen=0;
            HashMap<Integer,Integer> map=new HashMap<>();
            for (int i=0;i<arr.length;i++){
                if (!map.containsKey(arr[i])){
                    map.put(arr[i],i);
                    curlen++;
                    if(curlen>maxlen)
                        maxlen=curlen;
                }else {
                    Integer last_index= map.get(arr[i]);
                    if (i-last_index>curlen){
                        curlen++;
                    }else{
                        curlen=i-last_index;
                    }
                    if(curlen>maxlen)
                        maxlen=curlen;
                    map.put(arr[i],i);
                }
            }
            return maxlen;
    }
    public static class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
  }

    public List<List<Integer>> levelOrder3(TreeNode root) {
        List<List<Integer>> res=new LinkedList<>();
        if (root==null)
            return res;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        int cur=1;
        int next=0;
        int level=1;
        List<Integer> temp=new LinkedList<>();
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            temp.add(poll.val);
            cur--;
            if (poll.left!=null) {
                queue.offer(poll.left);
                next++;
            }
            if (poll.right!=null) {
                queue.offer(poll.right);
                next++;
            }
            if (cur==0){
                if ((level&1)==0)
                    Collections.reverse(temp);
                res.add(temp);
                temp=new LinkedList<>();
                cur=next;
                next=0;
                level++;
            }
        }
        return res;
    }



    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res=new ArrayList<>();
        if (root==null)
            return res;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()){
            LinkedList<Integer> tmp=new LinkedList<>();
            while (!queue.isEmpty()){
                TreeNode poll = queue.poll();
                if ((res.size()&1)==0)
                    tmp.addFirst(poll.val);
                else
                    tmp.addLast(poll.val);
                if (poll.left!=null) queue.add(poll.left);
                if (poll.right!=null) queue.add(poll.right);
            }
            res.add(tmp);
        }
        return res;
    }
    class Node {
        int val;
        Node next;
        Node random;

        public Node(int val) {
            this.val = val;
            this.next = null;
            this.random = null;
        }
    }
    public Node copyRandomList(Node head) {
        if (head==null)
            return null;
        //copy
        Node index=head;
        while (index!=null){
            Node copy=new Node(index.val);
            copy.next=index.next;
            index.next=copy;
            index=copy.next;
        }
        //copy random
        index=head;
        while (index!=null){
            if (index.random!=null){
                index.next.random=index.random.next;
            }
            index=index.next.next;
        }
        //split
        Node copyHead=head.next;
        Node cur=head;
        Node curcopy=head.next;
        while (cur!=null){
            cur.next=cur.next.next;
            cur=cur.next;
            if (curcopy.next!=null){
                curcopy.next=curcopy.next.next;
                curcopy=curcopy.next;
            }
        }
        return copyHead;
    }

    public int numIslands(char[][] grid) {
        if (grid.length==0||grid[0].length==0)
            return 0;
        int count=0;
        for (int i=0;i<grid.length;i++){
            for (int j=0;j<grid[0].length;j++){
                if (grid[i][j]=='1'){
                    count++;
                    infect(grid,i,j);
                }
            }
        }
        return count;
    }

    public void infect(char[][] grid,int x,int y){
        if (x<0||x>=grid.length||y<0||y>grid[0].length||grid[x][y]!='1')
            return;
        //infect
        grid[x][y]=2;
        infect(grid,x+1,y);
        infect(grid,x-1,y);
        infect(grid,x,y+1);
        infect(grid,x,y-1);
    }

    public int strStr(String haystack, String needle) {
        if (haystack==null||needle==null) return -1;
        char[] char1 = haystack.toCharArray();
        char[] char2= needle.toCharArray();
        if (char1.length< char2.length)
            return -1;
        int i=0;
        int j=0;
        int[] next=getNextArray(char2);
        while (i< char1.length&&j< char2.length){
            if (char1[i]==char2[j]){
                i++;
                j++;
            }else if (next[j]==-1)
                i++;
            else
                j=next[j];
        }
        return j== char2.length?i-j:-1;
    }

    public int[] getNextArray(char[] s){
        if (s.length==1) return new int[]{-1};
        int[] next=new int[s.length];
        next[0]=-1;
        next[1]=0;
        int i=2;
        int cn=0;
        while (i<s.length){
            if (s[i-1]==s[cn]){
                next[i]=cn+1;
                cn+=1;
                i++;
            }else if (cn>0)
                cn=next[cn];
            else
                next[i++]=0;
        }
        return next;
    }

    public boolean isCompleteTree (TreeNode root) {
        // write code here
        if(root==null)
            return true;
        Boolean empty=false;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if (poll==null)
                empty=true;
            else{
                if (empty)
                    return false;
                queue.offer(poll.left);
                queue.offer(poll.right);
            }
        }
        return true;
    }


    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if (pRoot==null)
            return res;
        Stack<TreeNode> oddNode=new Stack<>();
        Stack<TreeNode> evenNode=new Stack<>();
        oddNode.push(pRoot);
        boolean isOdd=true;
        while (!oddNode.isEmpty()||!evenNode.isEmpty()){
            ArrayList<Integer> tmp=new ArrayList<>();
            if (isOdd){
                while (!oddNode.isEmpty()){
                    TreeNode pop = oddNode.pop();
                    tmp.add(pop.val);
                    if (pop.left!=null)
                        evenNode.push(pop.left);
                    if (pop.right!=null)
                        evenNode.push(pop.right);
                }
            }else {
                TreeNode pop = evenNode.pop();
                tmp.add(pop.val);
                if (pop.left!=null)
                    oddNode.push(pop.left);
                if (pop.right!=null)
                    oddNode.push(pop.right);
            }
            res.add(tmp);
        }
        return res;
    }


    public int minCostClimbingStairs (int[] cost) {
        // write code here
        if (cost.length==1||cost.length==2)
            return 0;
        int[] dp=new int[cost.length];
        int max=Integer.MIN_VALUE;
        for (int i=3;i<dp.length;i++){
            dp[i]=Math.max(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
            max=dp[i]>max?dp[i]:max;
        }
        return max;


    }


    public int uniquePaths (int m, int n) {
        // write code here
        int[][] dp=new int[m][n];
        for (int i=0;i<n;i++)
            dp[0][i]=1;
        for (int j=0;j<m;j++)
            dp[j][0]=1;
        for (int i=1;i<m;i++){
            for (int j=1;j<n;j++){
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }


    public int minMoney (int[] arr, int aim) {
        // write code here
        if (aim==0)
            return 0;
        if (arr.length==0)
            return -1;
        int[] dp=new int[aim+1];
        dp[0]=0;
        for (int i=1;i<dp.length;i++)
            dp[i]=Integer.MAX_VALUE;
        Arrays.sort(arr);
        for(int i=1;i<dp.length;i++){
            for (int j=0;j<arr.length;j++){
                if (arr[j]<=dp[i])
                    dp[i]= Math.min(dp[i],dp[i-arr[j]+1]);
                else
                    break;
            }
        }
        return dp[aim]==Integer.MAX_VALUE?-1:dp[aim];
    }

    public int maxProfit2 (int[] prices) {
       if (prices.length==1)
           return 0;
       int[][] dp=new int[prices.length][2];
       dp[0][0]=0;//第0列代表不持有股票
       dp[0][1]=-prices[0];//第1列代表持有股票
        for (int i=1;i< prices.length;i++){
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+ prices[i]);
            dp[i][1]=Math.max(dp[i-1][1],-prices[i]);
        }
        return dp[prices.length-1][0];
    }

    //买卖股票2
    public int maxProfit4 (int[] prices) {
        // write code here
        if (prices.length==1)
            return 0;
        int[][] dp=new int[prices.length][2];
        dp[0][0]=0;//不持有股票
        dp[0][1]=-prices[0];//持有股票
        for (int i=1;i<dp.length;i++){
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+ prices[i]);
            dp[i][1]=Math.max(dp[i-1][0]-prices[i],dp[i-1][i]);
        }
        return dp[dp.length-1][0];
    }

    public int rob2 (int[] nums) {
        // write code here
        if(nums.length==1)
            return nums[0];
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        dp[1]=num[0]>nums[1]?nums[0]:nums[1];
        for (int i=2;i<dp.length;i++)
            dp[i]=Math.max(dp[i-2]+nums[i],dp[i-1]);
        return dp[nums.length-1];
    }

    //环形
    public int rob (int[] nums) {
        // write code here
        if (nums.length==1)
            return nums[0];
        //分两种情况，偷了第一家，和没偷第一家
        //情况一：偷了第一家，那么此时就一定不能偷最后一家了
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        dp[1]=nums[0];
        for (int i=2;i<dp.length-1;i++)
            dp[i]=Math.max(dp[i-2]+nums[i],dp[i-1]);

        //情况二：不偷第一家
        int[] dp2=new int[nums.length];
        dp[0]=0;
        dp[1]=nums[1];
        for (int i=2;i<dp.length-1;i++)
            dp2[i]=Math.max(dp2[i-2]+nums[i],dp2[i-1]);

        return dp[nums.length-2]>dp2[nums.length-1]?dp[nums.length-2]:dp2[nums.length-1];
    }

    public int minPathSum (int[][] matrix) {
        // write code here
        int[][] dp=new int[matrix.length][matrix[0].length];
        dp[0][0]=matrix[0][0];
        for (int i=1;i<matrix[0].length;i++)
            dp[0][i]=dp[0][i-1]+matrix[0][i-1];
        for (int j=1;j<matrix.length;j++)
            dp[j][0]=dp[j-1][0]+matrix[j-1][0];
        for (int i=1;i<matrix.length;i++){
            for (int j=1;j<matrix[0].length;j++){
                dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1])+matrix[i][j];
            }
        }
        return dp[matrix.length-1][matrix[0].length-1];
    }

    public String LCS (String str1, String str2) {
        // write code here
        int[][] dp=new int[str1.length()+1][str2.length()+1];
        int maxlen=Integer.MIN_VALUE;
        int index=0;
        for (int i=0;i<str1.length();i++)
            dp[i][0]=0;
        for (int j=0;j<str2.length();j++)
            dp[0][j]=0;
        for (int i=1;i<str1.length();i++){
            for (int j=1;j<str2.length();j++){
                if (str1.charAt(i-1)==str2.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+1;
                    if (dp[i][j]>maxlen) {
                        maxlen = dp[i][j];
                        index=i-1;
                    }
                }else {
                    dp[i][j]=0;
                }
            }
        }
        return str1.substring(index-maxlen+1,index+1);
    }

    public int translateNum(int num) {
        if (num<10) return 1;
        String s= cast(num);
        char[] chars = s.toCharArray();
        int[] dp=new int[chars.length];
        dp[0]=1;
        dp[1]=((chars[0]-'0')*10+ chars[1]-'0')<=25?2:1;
        for (int i=2;i< chars.length;i++){
            int pre=chars[i-1]-'0';
            int cur=chars[i]-'0';
            int tmp=pre*10+cur;
            if (tmp>=10&&tmp<26)
                dp[i]=dp[i-1]+dp[i-2];
            else
                dp[i]=dp[i-1];
        }
        return dp[dp.length-1];
    }

    public String cast(int num){
        StringBuilder sb=new StringBuilder();
        int base=10;
        while (num>0){
            int i=num%base;
            sb.append(i);
            num=num/base;
        }
        return sb.reverse().toString();
    }

    public int lengthOfLongestSubstring2(String s) {
            if (s==null||s.length()==0)
                return 0;
            if (s.length()==1)
                return 1;
            HashMap<Character,Integer> map=new HashMap<>();
            int j=0;
            int len=0;
            int maxlen=Integer.MIN_VALUE;
            while (j<s.length()){
                if (!map.containsKey(s.charAt(j)))
                    len++;
                else {
                    int last_index = map.get(s.charAt(j));
                    int gap=j-last_index;
                    if (gap>len)
                        len++;
                    else {
                        len=gap;
                    }
                }
                map.put(s.charAt(j),j++);
                maxlen=Math.max(maxlen,len);
            }
            return maxlen;
    }
    //2 3 5
    public int nthUglyNumber(int n) {
        if (n==1)
            return 1;
        int[] dp=new int[n+1];
        dp[1]=1;
        int x=1;
        int y=1;
        int z=1;
        for (int i=2;i<=n;i++){
            dp[i]=Math.min(dp[x]*2,Math.min(dp[y]*3,dp[z]*5));
            if (dp[i]==dp[x]*2)
                x++;
            if (dp[i]==dp[y]*3)
                y++;
            if (dp[z]==dp[z]*5)
                z++;
        }
        return dp[n];
    }

    public int search4(int[] nums, int target) {
        if (nums.length==0||nums[0]>target||nums[nums.length-1]<target)
            return 0;
        if (nums[0]==target&&nums[nums.length-1]==target)
            return nums.length;
        int left = find_left(nums, target, 0, nums.length - 1);
        int right = find_right(nums, target, 0, nums.length - 1);
        if (left>-1&&right>-1)
            return (right-left+1);
        else
            return -1;
    }

    public int find_left(int[] nums,int target,int left,int right){
        if (left>right)
            return -1;
        int mid=left+(right-left)/2;
        int midnum=nums[mid];
        if (midnum==target){
            if ((mid>0&&nums[mid-1]!=target)||mid==0)
                return mid;
            else
                right=mid-1;
        }else if (midnum>target)
            right=mid-1;
        else if (mid<target)
            left=mid+1;
        return find_left(nums,target,left,right);
    }

    public int find_right(int[] nums,int target,int left,int right){
        if (left>right)
            return -1;
        int mid=left+(right-left)/2;
        int midnum=nums[mid];
        if (midnum==target){
            if ((mid<nums.length-1&&nums[mid+1]!=target)||mid==nums.length-1)
                return mid;
            else
                left=mid+1;
        }else if (midnum>target)
            right=mid-1;
        else if (mid<target)
            left=mid+1;
        return find_right(nums,target,left,right);
    }

    public List<Integer> getAllElements2(TreeNode root1, TreeNode root2) {
            if (root1==null&&root2==null)
                return new ArrayList<>();
            ArrayList<Integer> res1=new ArrayList<>();
            ArrayList<Integer> res2=new ArrayList<>();
            traverse(root1,res1);
            traverse(root2,res2);
            if (res1==null)
                return res2;
            if (res2==null)
                return res1;
            ArrayList<Integer> res = merge(res1, res2);
            return res;

    }
    public void traverse(TreeNode t,ArrayList<Integer> res){
        if (t==null)
            return;
        traverse(t.left,res);
        res.add(t.val);
        traverse(t.right,res);
    }

    public ArrayList<Integer> merge(List<Integer> l1,List<Integer> l2){
        int size1= l1.size();
        int size2= l2.size();
        ArrayList<Integer> res=new ArrayList<>(size1+size2);
        int i=0;
        int j=0;
        int r=0;
        while (i<l1.size()&&j<l2.size()){
            if (l1.get(i)<l2.get(j))
                res.add(r++,l1.get(i++));
            else
                res.add(r++,l2.get(j++));
        }
        while (i<l1.size())
            res.add(r++,l1.get(i++));
        while (j<l2.size())
            res.add(r++,l2.get(j++));
        return res;
    }

    //突然想到一个这个题的感觉还可以解答的办法
    //用小顶堆
    public List<Integer> getAllElements(TreeNode root1, TreeNode root2) {
        if (root1==null&&root2==null)
            return new ArrayList<>();
        PriorityQueue<TreeNode> res=new PriorityQueue<>(Comparator.comparingInt(node -> node.val));
        traverse(root1,res);
        traverse(root2,res);
        ArrayList<Integer> list=new ArrayList<>();
        while (!res.isEmpty()){
            TreeNode poll = res.poll();
            list.add(poll.val);
        }
        return list;
    }
    public void traverse(TreeNode t,PriorityQueue<TreeNode> queue){
        if (t==null)
            return;
        traverse(t.left,queue);
        queue.add(t);
        traverse(t.right,queue);
    }

    private int countPairs=0;
    public int reversePairs(int[] nums) {
        if (nums.length==0||nums.length==1)
            return 0;
        mergeSort(nums,0,nums.length-1);
        return countPairs;
    }
    public void mergeSort(int[] nums,int left,int right){
        if (left>=right)
            return;
        int mid=left+(right-left)/2;
        mergeSort(nums,left,mid-1);
        mergeSort(nums,mid+1,right);
        mergeWithCount(nums,left,right,mid);
    }
    public void mergeWithCount(int[] nums,int left,int right,int mid){
        int[] res=new int[right-left+1];
        int i=mid;
        int j=right;
        int index=res.length-1;
        while (i>=left&&j>mid){
            if (nums[i]>=nums[j]){
                countPairs+=(j-mid);
                res[index--]=nums[i--];
            }else {
                res[index--]=nums[j--];
            }
        }
        while (i>=left)
            res[index--]=nums[i--];
        while (j>mid)
            res[index--]=nums[j--];
        for (int z=left;z<=right;z++){
            nums[z]=res[z-left];
        }
    }

    //dp
    public int LIS2 (int[] arr) {
        // write code here
        if(arr.length==0) return 0;
        if (arr.length==1) return 1;

        //dp代表以这个当前下标结尾的最长子序列
        int[] dp=new int[arr.length];
        dp[0]=1;
        dp[1]=arr[1]>arr[0]?2:1;
        for (int j=2;j<dp.length;j++)
            dp[j]=1;
        int maxlen=dp[0];
        for (int j=2;j<dp.length;j++){
            for (int i=0;i<j;i++){
                if (arr[i]<arr[j]){
                    dp[j]=Math.max(dp[j],dp[i]+1);
                }
            }
            maxlen=Math.max(dp[j],maxlen);
        }
        return maxlen;
    }
    //binary search
    public int LIS (int[] arr) {
            if (arr.length==0) return 0;
            if (arr.length==1) return 1;
            int[] res=new int[arr.length];
            res[0]=arr[0];
            int end=0;
            for (int i=1;i<res.length;i++){
                if (arr[i]>res[end])
                    res[++end]=arr[i];
                else {
                    int left = findLeft(arr, 0, end, res[i]);
                    res[left]=arr[i];
                }
            }
            return end+1;
    }
    public static int findLeft(int[] arr,int left,int right,int target){
        int l=left;
        int r=right;
        while (l<r){
            int mid=l+(r-l)/2;
            if (arr[mid]>=target)
                r=mid;
            else
                l=mid+1;
        }
        return l;
    }

    //最长公共子序列
    //这破题，真是气死我了！！！！
    public static String LCS2 (String s1, String s2) {
        // write code here
        if (s1==null&&s2==null||(s1.length()==0&&s2.length()==0)) return "-1";
        if (s1==null||s2==null||s1.length()==0||s2.length()==0) return "-1";
        int[][] dp=new int[s1.length()+1][s2.length()+1];
        int[][] tmp=new int[s1.length()+1][s2.length()+1];
        for (int i=0;i<=s1.length();i++)
            dp[i][0]=0;
        for (int j=0;j<=s2.length();j++)
            dp[0][j]=0;
        for (int i=1;i<dp.length;i++){
            for (int j=1;j<dp[0].length;j++){
                if (s1.charAt(i-1)==s2.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+1;
                    tmp[i][j]=3;//3代表左上
                }else {
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                    tmp[i][j]=dp[i][j]==dp[i][j-1]?1:2;//1代表左，2代表上
                }
            }
        }
        for (int i=0;i< tmp.length;i++){
            for (int j=0;j<tmp[0].length;j++){
                System.out.print(tmp[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println("-------");
        for (int i=0;i< dp.length;i++){
            for (int j=0;j<dp[0].length;j++){
                System.out.print(dp[i][j]+" ");
            }
            System.out.println();
        }
        if (dp[s1.length()][s2.length()]==0)
            return "-1";
        StringBuilder sb=new StringBuilder();
        int i=s1.length();
        int j=s2.length();
        while (i>0&&j>0){
            if (tmp[i][j]==1) j--;
            else if (tmp[i][j]==2) i--;
            else{
                sb.append(s1.charAt(i-1));
                i--;
                j--;
            }
        }
        return sb.reverse().toString();

    }
    public static String ans(int i, int j, int[][] b, String x){
        String res = "";
        //递归终止条件
        if(i == 0 || j == 0)
            return res;
        //根据方向，往前递归，然后添加本级字符
        if(b[i][j] == 3){
            res += ans(i - 1, j - 1, b,x);
            res += x.charAt(i - 1);
        }
        else if(b[i][j] == 2)
            res += ans(i - 1, j, b,x);
        else if(b[i][j] == 1)
            res += ans(i,j - 1, b,x);
        return res;
    }



    public static int findTheWinner(int n, int k) {
        Queue<Integer> queue=new LinkedList<>();
        for (int i=1;i<=n;i++)
            queue.offer(i);
        while (queue.size()!=1){
            for (int i=1;i<k;i++){
                queue.offer(queue.poll());
            }
            queue.poll();
        }
        return queue.poll();
    }

    public int findTheWinner2(int n, int k) {
        if (n==1)
            return 1;
        int[] dp=new int[n+1];
        dp[1]=1;
        for (int i=2;i<=n;i++){
            dp[i]=(dp[i-1]+k)%i;
        }
        return dp[n];
    }

    public static int longestValidParentheses(String s) {
        if (s.length()==0||s=="") return 0;
        int[] dp=new int[s.length()];
        dp[0]=0;
        dp[1]=s.charAt(0)=='('&&s.charAt(1)==')'?2:0;
        int max=dp[1];
        for (int i=2;i<s.length();i++){
            if (s.charAt(i)==')'){
                int gap=dp[i-1];
                int j=i-gap-1;
                if (j>=0){
                    if (s.charAt(j)=='(') {
                        dp[i] += dp[i - 1] + 2;
                        if (j-1>=0)
                            dp[i]+=dp[j-1];
                    }
                }
            }
            max= Math.max(dp[i],max);
        }
        return max;
    }

    public int numSubarrayProductLessThanK(int[] nums, int k) {
            int res=0;
            int i=0;
            int j=0;
            int tmp=1;
            while (j<nums.length){
                tmp*=nums[j];
                while (i<=j&&tmp>k){
                    tmp/=nums[i];
                    i++;
                }
                res+=j-i+1;
            }
            return res;
    }

    public int missingNumber(int[] nums) {
            int left=0;
            int right=nums.length;
            int mid=0;
            while (left<=right){
                mid=left+((right-left)>>1);
                if (nums[mid]!=mid){
                    if (mid==0||nums[mid-1]==mid-1)
                        return mid;
                    right=mid-1;
                }else
                    left=mid+1;
            }
            if (left==nums.length-1)
                return nums.length-1;
            return -1;
    }

    class returnType{
        boolean isbalanced=false;
        int depth=0;

        public returnType(boolean b,int d){
            this.isbalanced=b;
            this.depth=d;
        }
    }

    public boolean isBalanced(TreeNode root) {
        if (root==null||(root.left==null&&root.right==null))
            return true;
        return help(root).isbalanced;
    }
    public returnType help(TreeNode node){
        if (node==null)
            return new returnType(true,0);
        returnType left = help(node.left);
        returnType right = help(node.right);
        boolean isbalanced=left.isbalanced&&right.isbalanced&&(Math.abs(left.depth-right.depth)<=1);
        int depth=left.depth>right.depth?left.depth+1:right.depth+1;
        return new returnType(isbalanced,depth);
    }

    public int[] singleNumbers(int[] nums) {
        int res=0;
        for (int i=0;i<nums.length;i++)
            res^=nums[i];
        //find the most right difference
        int j=res&(res-1);
        int a=0;
        int b=0;
        for (int i=0;i<nums.length;i++){
            if ((nums[i]&j)==1)
                a^=nums[i];
            else
                b^=nums[i];
        }
        return new int[]{a,b};
    }

    public int singleNumber2(int[] nums) {
        int[] countArr=new int[32];
        for (int num:nums)
            count(num,countArr);
        int res=0;
        for (int i=0;i< countArr.length;i++){
            if (countArr[i]%3!=0){
                res+=Math.pow(2,i);
            }
        }
        return res;
        /*
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            int total = 0;
            for (int num: nums) {
                total += ((num >> i) & 1);
            }
            if (total % 3 != 0) {
                ans |= (1 << i);
            }
        }
        return ans;
         */
    }
    public void count(int num,int[] countArr){
        int index=0;
        while (num>0){
            int flag=num&1;
            countArr[index]+=flag;
            num=num>>1;
            index++;
        }
    }

    public int singleNumber(int[] nums) {
        int res=0;
        for (int i=0;i<32;i++){
            int count=0;
            for (int j=0;j<nums.length;j++)
                res+=((nums[j]>>i)&1);
            if (count%3!=0)
                res|=(1<<i);
        }
        return res;
    }

    public int numSubarrayProductLessThanK2(int[] nums, int k) {
        if(k==0)
            return 0;
        int i=0;
        int j=0;
        int res=0;
        int tmp=1;
        while (j<nums.length){
            tmp*=nums[j];
            while (i<=j&&tmp>k){
                tmp/=nums[i];
                i++;
            }
            res+=(j-i+1);
        }
        return res;
    }

    public int minMutation(String start, String end, String[] bank) {
        if (start.equals(end))
            return 0;
        HashSet<String> bankset=new HashSet<>();
        for (String s:bank)
            bankset.add(s);
        if (!bankset.contains(end))
            return -1;
        HashSet<String> visited=new HashSet<>();
        char[] keys=new char[]{'A','C','G','T'};
        Queue<String> queue=new LinkedList<>();
        queue.offer(start);
        visited.add(start);
        int count=0;
        while (!queue.isEmpty()){
            int size = queue.size();
            while (size-->0){
                String poll = queue.poll();
                for (int i=0;i<8;i++){
                    for (int j=0;j<4;j++){
                        if (keys[j]!=poll.charAt(i)){
                            StringBuilder sb=new StringBuilder(poll);
                            sb.setCharAt(i,keys[j]);
                            String s = sb.toString();
                            if (!visited.contains(s)&&bankset.contains(s)){
                                if (s.equals(end))
                                    return count;
                                visited.add(s);
                                queue.offer(s);
                            }
                        }
                    }
                }
            }
            count++;
        }
        return -1;

    }

    private List<List<Integer>> pathSum=new ArrayList<>();
    private List<Integer> tmp=new ArrayList<>();
    public List<List<Integer>> pathSum2(TreeNode root, int target) {
            if (root==null)
                return pathSum;
            getSum(root,0,target);
            return pathSum;
    }
    public void getSum(TreeNode node,int pre_sum,int target){
        if (node==null)
            return;
        pre_sum+= node.val;
        tmp.add(node.val);
        if (node.left==null&&node.right==null){
            if (pre_sum==target)
                pathSum.add(tmp);
        }
        getSum(node.left,pre_sum,target);
        getSum(node.right,pre_sum,target);
        tmp.remove(tmp.size()-1);
    }

    public int findMinMoves(int[] machines) {
        if (machines==null||machines.length==0)
            return 0;
        int sum=0;
        for (int i=0;i<machines.length;i++)
            sum+=machines[i];
        if (sum%machines.length!=0)
            return -1;
        int average=sum/machines.length;
        int leftsum=0;
        int ans=0;
        for (int i=0;i<machines.length;i++){
            int L=i*average-leftsum;
            int R=(machines.length-i-1)*average-(sum-leftsum-machines[i]);
            if (L>0&&R>0){
                ans=Math.max(ans,(Math.abs(L)+Math.abs(R)));
            }else {
                ans=Math.max(ans,Math.max(Math.abs(L),Math.abs(R)));
            }
            leftsum+=machines[i];
        }
        return ans;
    }

    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        if (head==null)
            return null;
        ListNode node1=head;
        ListNode node2=head.next;
        while (node2!=null){
            while (node2!=null&&node1.val==node2.val) node2=node2.next;
            if (node1.next!=node2)
                node1.next=node2;
            if (node2==null)
                break;
            node1=node1.next;
            node2=node2.next;
        }
        return head;
    }

    public ListNode deleteDuplicates2 (ListNode head) {
        // write code here
        if (head==null)
            return head;
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        ListNode pre=dummy;
        ListNode res=dummy;
        ListNode cur1=head;
        ListNode cur2=head.next;
        while (cur2!=null){
            while (cur2!=null&&cur2.val==cur1.val) cur2=cur2.next;
            if (cur1.next==cur2){
                if (cur2==null)
                    break;
                dummy=dummy.next;
                cur1=cur1.next;
                cur2=cur2.next;
            }else {
                dummy.next=cur2;
                if (cur2==null)
                    break;
                cur1=cur2;
                cur2=cur1.next;
            }
        }
        return res.next;
    }

    private ArrayList<Integer> inorder=new ArrayList();
    public int[] inorderTraversal (TreeNode root) {
        // write code here
        if (root==null)
            return new int[]{};
        helpin(root);
        int[] res=new int[inorder.size()];
        for (int i=0;i<res.length;i++)
            res[i]=inorder.get(i);
        return res;
    }
    public void helpin(TreeNode root){
        if (root==null)
            return;
        helpin(root.left);
        inorder.add(root.val);
        helpin(root.right);
    }

    public int findPeakElement2 (int[] nums) {
        if (nums.length==1||nums[0]>nums[1])
            return 0;
        if (nums[nums.length-2]<nums[nums.length-1])
            return nums.length-1;
        int left=0;
        int right=nums.length-1;
        while (left<right){
            int mid=left+(right-left)/2;
            if (nums[mid-1]<nums[mid]&&nums[mid]>nums[mid+1])
                return mid;
            if (nums[mid-1]<nums[mid])
                left=mid;
            else if (nums[mid-1]>=nums[mid])
                right=mid-1;
        }
        return left;
    }

    public TreeNode mergeTrees22 (TreeNode t1, TreeNode t2) {
        // write code here
        if (t1==null&&t2==null)
            return null;
        if (t1==null)
            return t2;
        if (t2==null)
            return t1;
        TreeNode res=new TreeNode(t1.val+t2.val);
        res.left=mergeTrees(t1.left,t2.left);
        res.right=mergeTrees(t1.right,t2.right);
        return res;
    }

    public class returnType4BST{
        int minval;
        int maxval;
        boolean isBST;

        public returnType4BST(int min,int max,boolean isBST){
            this.minval=min;
            this.maxval=max;
            this.isBST=isBST;
        }

    }
    public boolean isValidBST (TreeNode root) {
        // write code here
        if (root==null)
            return true;
        return helpbst(root).isBST;

    }

    public returnType4BST helpbst(TreeNode node){
        if (node==null)
            return null;
        returnType4BST leftreturn=helpbst(node.left);
        returnType4BST rightreturn=helpbst(node.right);

        int min= node.val;
        int max= node.val;

        if (leftreturn!=null){
            min=Math.min(min,leftreturn.minval);
            max=Math.max(max,leftreturn.maxval);
        }
        if (rightreturn!=null){
            min=Math.min(min,rightreturn.minval);
            max=Math.max(max,rightreturn.maxval);
        }

        boolean isbst=true;
        if (leftreturn!=null&&(!leftreturn.isBST||leftreturn.maxval> node.val))
            isbst=false;
        if (rightreturn!=null&&(!rightreturn.isBST||rightreturn.minval< node.val))
            isbst=false;

        return new returnType4BST(min,max,isbst);
    }

    public class nd {
        int val;
        nd left;
        nd right;
        nd(int x) { val = x; }
    }

    public int[] solve (int[] xianxu, int[] zhongxu) {
        // write code here
        nd nd = buildTree2(xianxu, zhongxu);
        Queue<nd> queue=new LinkedList<>();
        queue.offer(nd);
        ArrayList<Integer> res=new ArrayList<>();
        while (!queue.isEmpty()){
            int size = queue.size();
            while (size>1){
                nd poll = queue.poll();
                if (poll.left!=null)
                    queue.offer(poll.left);
                if (poll.right!=null)
                    queue.offer(poll.right);
                size--;
            }
            nd tmp = queue.poll();
            res.add(tmp.val);
            if (tmp.left!=null)
                queue.offer(tmp.left);
            if (tmp.right!=null)
                queue.offer(tmp.right);
        }
        int[] arr=new int[res.size()];
        for (int i=0;i<arr.length;i++)
            arr[i]=res.get(i);
        return arr;
    }

    public nd buildTree2(int[] xianxu,int[] zhongxu){
        if (xianxu.length==0)
            return null;
        if (xianxu.length==1)
            return new nd(xianxu[0]);
        int root=xianxu[0];
        int index=0;
        for (int i=0;i< zhongxu.length;i++){
            if (zhongxu[i]==root){
                index=i;
                break;
            }
        }
        int[] lxianxu = Arrays.copyOfRange(xianxu, 1, 1 + index);
        int[] rxianxu=Arrays.copyOfRange(xianxu,1+index,xianxu.length);
        int[] lzhongxu=Arrays.copyOfRange(zhongxu,0,index);
        int[] rzhongxu=Arrays.copyOfRange(zhongxu,index+1,zhongxu.length);
        nd node=new nd(xianxu[0]);
        node.left=buildTree2(lxianxu,lzhongxu);
        node.right=buildTree2(rxianxu,rzhongxu);
        return node;
    }

    public boolean isValid (String s) {
        // write code here
        if (s.length()==0||s==null)
            return true;
        char[] chars = s.toCharArray();
        Stack<Character> stack=new Stack<>();
        HashSet<Character> set=new HashSet<>();
        set.add('}');
        set.add(']');
        set.add(')');
        HashMap<Character,Character> map=new HashMap<>();
        map.put(')','(');
        map.put('}','{');
        map.put(']','[');
        for (int i=0;i< chars.length;i++){
            if (set.contains(chars[i])){
                Character pattern = map.get(chars[i]);
                if (stack.size()==0||stack.pop()!=pattern)
                    return false;
            }else {
                stack.push(chars[i]);
            }
        }
        return stack.isEmpty();
    }


    public int[] twoSum (int[] numbers, int target) {
        // write code here
        if(numbers.length==0)
            return null;
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<numbers.length;i++){
            if (map.containsKey(target-numbers[i])){
                return new int[]{map.get(target-numbers[i])+1,i+1};
            }else
                map.put(numbers[i],i);
        }
        return null;
    }

    public int minNumberDisappeared2 (int[] nums) {
        // write code here
        if (nums.length==0)
            return 1;
        int len=nums.length;
        HashSet<Integer> set=new HashSet<>();
        for (int i=0;i<len;i++)
            set.add(nums[i]);
        for (int i=1;i<=len;i++){
            if (!set.contains(i))
                return i;
        }
        return len+1;
    }

    public int minNumberDisappeared (int[] nums) {
        if (nums.length==0)
            return 1;
        for (int i=0;i<nums.length;i++){
            if (nums[i]<=0)
                nums[i]=nums.length+1;
        }
        for (int i=0;i<nums.length;i++){
            int abs = Math.abs(nums[i]);
            if (abs<=nums.length)
                nums[abs-1]=-1*Math.abs(nums[abs-1]);
        }
        for (int i=0;i<nums.length;i++){
            if (nums[i]>0)
                return i+1;
        }
        return nums.length+1;
    }

    //三数之和，这个答案不对，不能去重复
    public ArrayList<ArrayList<Integer>> threeSum2(int[] num) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if (num.length<3)
            return res;
        int[] tmp=new int[num.length];
        for (int i=0;i<tmp.length;i++)
            tmp[i]=0-num[i];
        for (int i=0;i<num.length-2;i++){
            int twosum=tmp[i];
            HashSet<Integer> set=new HashSet<>();
            for (int j=i+1;j<num.length;j++){
                if (set.contains(twosum-num[j])){
                    ArrayList<Integer> r = new ArrayList<>();
                    r.add(num[j]);
                    r.add(twosum-num[j]);
                    r.add(num[i]);
                    if (!res.contains(r))
                        res.add(r);
                }else {
                    set.add(num[j]);
                }
            }
        }
        return res;
    }

    //三数之和，正解
    public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if (num==null||num.length<3)
            return res;
        Arrays.sort(num);
        for (int i=0;i<num.length-2;i++){
            if (num[i]>0) break;
            if (i>0&&num[i]==num[i-1]) continue;
            int target=-num[i];
            int left=i+1;
            int right=num.length-1;
            while (left<right){
                if (num[left]+num[right]==target) {
                    res.add(new ArrayList<>(Arrays.asList(num[i],num[left],num[right])));
                    left++;
                    right--;
                    while (left<right&&num[left]==num[left-1]) left++;
                    while (left<right&&num[right]==num[right+1]) right--;
                }else if (num[left]+num[right]<target){
                    left++;
                }else {
                    right--;
                }
            }
        }
        return res;
    }

    //k个一组反转链表，看的leetcode上面的代码
    public ListNode reverseKGroup_ (ListNode head, int k) {
        // write code here
        if (head==null||head.next==null)
            return head;

        ListNode dummy=new ListNode(0);
        dummy.next=head;

        ListNode pre=dummy;
        ListNode end=dummy;

        while (end.next!=null){
            for (int i=0;i<k&&end!=null;i++)
                end=end.next;
            if (end==null)
                break;
            ListNode start=pre.next;
            ListNode next=end.next;
            end.next=null;
            pre.next=reverse4k(start);
            start.next=next;

            pre=start;
            end=pre;
        }

        return dummy.next;
    }

    private ListNode reverse4k(ListNode head){
        if (head==null||head.next==null)
            return head;
        ListNode pre=null;
        ListNode cur=head;
        ListNode next=null;
        while (cur!=null){
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

    //再写一遍
    public ListNode reverseKGroup4(ListNode head, int k) {
        if (head==null||head.next==null)
            return head;

        ListNode dummy=new ListNode(0);
        dummy.next=head;

        ListNode pre=dummy;
        ListNode end=dummy;

        while (end.next!=null){
            for (int i=0;i<k&&end!=null;i++)
                end=end.next;
            if (end==null)
                break;
            ListNode start=pre.next;
            ListNode next=end.next;
            end.next=null;
            pre.next=rev(start);
            start.next=next;

            pre=start;
            end=pre;
        }
        return dummy.next;
    }
    
    public ListNode rev(ListNode head){
        if (head==null||head.next==null)
            return head;
        ListNode pre=null;
        ListNode cur=head;
        ListNode next=null;
        while (cur!=null){
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

    //接雨水问题
    public int trap(int[] height) {
        int length = height.length;
        int[] leftMax=new int[length];
        leftMax[1]= height[0];
        for (int i=2;i<leftMax.length-1;i++){
            leftMax[i]=Math.max(leftMax[i-1], height[i-1]);
        }
        int[] rightMax=new int[length];
        rightMax[height.length-2]=height[height.length-1];
        for (int i= height.length-3;i>0;i--){
            rightMax[i]=Math.max(rightMax[i+1], height[i+1]);
        }
        int res=0;
        for (int i=1;i< height.length-1;i++){
            res+=Math.max(0,Math.min(leftMax[i],rightMax[i])- height[i]);
        }
        return res;
    }

    public int minArray(int[] numbers) {
        if (numbers.length==1)
            return numbers[0];
        int l=0;
        int r=numbers.length-1;
        while (l<r){
            int mid=l+(r-l)/2;
            if (numbers[mid]<numbers[r])
                r=mid;
            else if (numbers[mid]>numbers[r])
                l=mid+1;
            else
                r--;
        }
        return numbers[l];
    }

    public int[][] findContinuousSequence(int target) {
        List<int[]> res=new ArrayList<>();
        int l=1;
        int r=2;
        while (l<r){
            int sum=(r-l+1)*(l+r)/2;
            if (sum==target){
                int[] temp=new int[r-l+1];
                for (int i=0;i<r-l+1;i++)
                    temp[i]=l+i;
                res.add(temp);
                l++;
            }else if (sum>target)
                l++;
            else
                r--;
        }
        return res.toArray(new int[res.size()][]);
    }

    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length==0)
            return nums;
        if (k<1||nums.length<k)
            return null;

        int[] res=new int[nums.length-k+1];
        int index=0;
        LinkedList<Integer> queue=new LinkedList<>();
        int r=0;
        while (r<nums.length){
            while (!queue.isEmpty()||nums[queue.peekLast()]<nums[r])
                queue.pollLast();
            queue.offerLast(r);

            if (queue.peek()+k<=r)
                queue.poll();

            if (r+1>=k)
                res[index++]=nums[queue.peek()];

        }
        return res;
    }

    public static class MinStack {
        private Stack<Integer> stack = new Stack();
        private Stack<Integer> min_stack = new Stack();

        public MinStack() {

        }

        public void push(int x) {
            stack.push(x);
            if (min_stack.isEmpty())
                min_stack.push(x);
            else {
                Integer tmp = min_stack.peek();
                if (tmp < x)
                    min_stack.push(tmp);
                else
                    min_stack.push(x);
            }
        }

        public void pop() {
            stack.pop();
            min_stack.pop();
        }

        public int top() {
            return stack.peek();
        }

        public int min() {
            return min_stack.peek();
        }
    }

    public int solve (char[][] grid) {
        // write code here
        if (grid.length==0||grid[0].length==0)
            return 0;
        int count=0;
        for (int i=0;i< grid.length;i++){
            for (int j=0;j< grid[0].length;j++){
                if (grid[i][j]=='1'){
                    count+=1;
                    infect4solve(grid,i,j);
                }
            }
        }
        return count;
    }
    public void infect4solve(char[][] grid,int x,int y){
        if (x<0||x>=grid.length||y<0||y>=grid[0].length)
            return;

        if (grid[x][y]=='1'){
            grid[x][y]='2';
            infect4solve(grid,x+1,y);
            infect4solve(grid,x-1,y);
            infect4solve(grid,x,y+1);
            infect4solve(grid,x,y-1);
        }

    }

    ArrayList<ArrayList<Integer>> res4permute=new ArrayList<>();
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        Arrays.sort(num);
        dfs(num,0);
        res4permute.sort(new Comparator<ArrayList<Integer>>() {
            @Override
            public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
                StringBuilder key1 = new StringBuilder();
                StringBuilder key2 = new StringBuilder();
                for (int i = 0; i < o1.size(); i++) {
                    key1.append(o1.get(i));
                    key2.append(o2.get(i));
                }
                return key1.toString().compareTo(key2.toString());
            }
        });
        return res4permute;
    }
    public void dfs(int[] num,int index){
        if (index==num.length){
            ArrayList<Integer> list = new ArrayList<>();
            for (int i=0;i<num.length;i++)
                list.add(num[i]);
            if (!res4permute.contains(list))
                res4permute.add(list);
            return;
        }
        for (int i=index;i<num.length;i++){
            if (i!=index&&num[i]==num[index]) continue;
            swap4permute(num,index,i);
            dfs(num,index+1);
            swap4permute(num,index,i);
        }
    }
    public void swap4permute(int[] num,int i,int j){
        int temp=num[i]^num[j];
        num[i]=temp^num[i];
        num[j]=temp^num[j];
    }

    private ArrayList<String> res4generate=new ArrayList<>();
    private int bound;
    private StringBuilder tmp4generate=new StringBuilder();

    public ArrayList<String> generateParenthesis (int n) {
        // write code here
        this.bound=n;
        dfs4fgenerate(0,0);
        return res4generate;
    }
    public void dfs4fgenerate(int l,int r){
        if (l>bound||r>bound)
            return;
        if (l==bound&&r==bound)
            res4generate.add(tmp4generate.toString());
        if (r<=l){
            tmp4generate.append('(');
            dfs4fgenerate(l+1,r);
            tmp4generate.deleteCharAt(tmp4generate.length()-1);
            tmp4generate.append(')');
            dfs4fgenerate(l,r+1);
            tmp4generate.deleteCharAt(tmp4generate.length()-1);
        }

    }

    /*
    这个解法不太对，看下面的把
    private boolean[][] visited;
    private int maxpath=Integer.MIN_VALUE;
    private int[][] dp;
    public int solve (int[][] matrix) {
        // write code here
        visited=new boolean[matrix.length][matrix[0].length];
        dp=new int[matrix.length][matrix[0].length];
        int res=0;
        for (int i=0;i< matrix.length;i++){
            for (int j=0;j<matrix[0].length;j++){
                dfs4path(matrix,i,j,0,-1);
                res=Math.max(maxpath,res);
                maxpath=Integer.MIN_VALUE;
                visited=new boolean[matrix.length][matrix[0].length];
            }
        }
        return res;
    }
    public void dfs4path(int[][] matrix,int x,int y,int prepath,int pre){
        if (x<0||x>=matrix.length||y<0||y>=matrix[0].length||visited[x][y]==true)
            return;
        if (matrix[x][y]>pre){
            prepath+=1;
            maxpath=Math.max(maxpath,prepath);
            visited[x][y]=true;
            pre= matrix[x][y];
            dfs4path(matrix,x+1,y,prepath,pre);
            dfs4path(matrix,x-1,y,prepath,pre);
            dfs4path(matrix,x,y+1,prepath,pre);
            dfs4path(matrix,x,y-1,prepath,pre);
            visited[x][y]=false;
        }
    }*/


    public int solve (int[][] matrix) {
        // write code here
        if (matrix==null||matrix.length==0||matrix[0].length==0)
            return 0;

        int max=0;
        int[][] dp=new int[matrix.length][matrix[0].length];
        for (int i=0;i< matrix.length;i++){
            for (int j=0;j<matrix[0].length;j++)
                max=Math.max(max,getMax(matrix,i,j,-1,dp));
        }
        return max;
    }
    public int getMax(int[][] matrix,int i,int j,int pre,int[][] dp){
        if (i<0||i<=matrix.length||j<0||j>=matrix[0].length||matrix[i][j]<=pre)
            return 0;

        if (dp[i][j]!=0)
            return dp[i][j];
        int ret=0;
        ret=Math.max(ret,getMax(matrix,i+1,j,matrix[i][j],dp));
        ret=Math.max(ret,getMax(matrix,i-1,j,matrix[i][j],dp));
        ret=Math.max(ret,getMax(matrix,i,j+1,matrix[i][j],dp));
        ret=Math.max(ret,getMax(matrix,i,j-1,matrix[i][j],dp));
        dp[i][j]=ret+1;
        return dp[i][j];
    }

    private ArrayList<String> res4ip=new ArrayList<>();
    private int seg_count=4;
    private int[] segments=new int[seg_count];
    public ArrayList<String> restoreIpAddresses (String s) {
        // write code here
        dfs4ip(s,0,0);
        return res4ip;
    }
    public void dfs4ip(String s,int segId,int start){
        if (segId==seg_count){
            if (start==s.length()){
                StringBuilder sb=new StringBuilder();
                for (int i=0;i<seg_count;i++){
                    sb.append(segments[i]);
                    if (i+1!=seg_count)
                        sb.append('.');
                }
                res4ip.add(sb.toString());
            }
            return;
        }
        if (start==s.length())
            return;
        if (s.charAt(start)=='0'){
            segments[segId]=0;
            dfs4ip(s,segId+1,start+1);
        }

        int addr=0;
        for (int end=start;end<s.length();end++){
            addr=addr*10+(s.charAt(end)-'0');
            if (addr>0&&addr<=255){
                segments[segId]=addr;
                dfs4ip(s,segId+1,end+1);
            }else
                break;
        }

    }

    public ListNode reverseKGroup2(ListNode head, int k) {
        if (head==null||head.next==null)
            return head;

        ListNode dummy=new ListNode(0);
        dummy.next=head;
        ListNode pre=dummy;
        ListNode end=dummy;

        while (end.next!=null){
            for (int i=0;i<k&&end!=null;i++)
                end=end.next;
            if (end==null)
                break;
            ListNode start=pre.next;
            ListNode next=end.next;
            end.next=null;
            pre.next=rever(start);
            start.next=next;
            pre=start;
            end=start;
        }
        return dummy.next;
    }
    public ListNode rever(ListNode node){
        if (node==null||node.next==null)
            return node;
        ListNode pre=null;
        ListNode cur=node;
        ListNode next=null;
        while (cur!=null){
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

    public int solve23 (String s) {
        Map<Character,Integer> priority=new HashMap<>();
        priority.put('+',1);
        priority.put('-',1);
        priority.put('*',2);
        Stack<Integer> nums=new Stack<>();
        Stack<Character> opts=new Stack<>();
        char[] chars = s.toCharArray();
        for(int i=0;i< chars.length;i++){
            char c = chars[i];
            if(c=='(')
                opts.push(c);
            else if (c==')'){
                while (opts.peek()!='(')
                    cal(nums,opts);
                opts.pop();
            }else if (Character.isDigit(c)){
                int num=0;
                int j=i;
                while (j< chars.length&&Character.isDigit(chars[j])){
                    num=num*10+(chars[j]-'0');
                    j++;
                }
                nums.push(num);
                i=j-1;
            }else {
                while (!opts.isEmpty()&&opts.peek()!='('&&map.get(opts.peek())>=map.get(c))
                    cal(nums,opts);
                opts.push(c);
            }
        }
        while (!opts.isEmpty())
            cal(nums,opts);
        return nums.pop();
    }
    public void cal(Stack<Integer> nums,Stack<Character> opts){
        int num2=nums.pop();
        int num1=nums.pop();
        char opt=opts.pop();
        if (opt=='+')
            nums.push(num1+num2);
        else if (opt=='*')
            nums.push(num1*num2);
        else
            nums.push(num1-num2);
    }

    public int[] maxSlidingWindow2(int[] nums, int k) {
        if (nums.length==0||nums.length<k||k<1)
            return nums;
        LinkedList<Integer> queue=new LinkedList<>();
        int l=0;
        int r=0;
        while (r<k){
            while (!queue.isEmpty()&&nums[queue.peekLast()]<nums[r])
                queue.pollLast();
            queue.offer(r);
            r++;
        }
        int[] res=new int[nums.length-k+1];
        res[0]=nums[queue.peek()];
        l++;
        int index=1;
        while (r<nums.length){
            while (!queue.isEmpty()&&nums[queue.peekLast()]<nums[r])
                queue.pollLast();
            queue.offer(r);
            if (queue.peek()<l)
                queue.poll();
            res[index++]=nums[queue.peek()];
            r++;
            l++;
        }
        return res;
    }

    public String trans(String s, int n) {
        // write code here
        StringBuilder res=new StringBuilder();
        int start=0;
        for (int i=n-1;i>=0;i--){
            if (s.charAt(i)==' '){
                res.append(' ');
                start=n-i;
            }else {
                char tmp=(char)(s.charAt(i)<97?s.charAt(i)+32:s.charAt(i)-32);
                res.insert(start,tmp);
            }
        }
        return res.toString();
    }

    public long maxWater (int[] arr) {
        // write code here
        if (arr==null||arr.length<=2)
            return 0;
        int leftMax=arr[0];
        int rightMax=arr[arr.length-1];
        int l=0;
        int r=arr.length-1;
        long res=0;
        while (l<r){
            int tmp=Math.min(leftMax,rightMax);
            if (tmp==leftMax){
                l++;
                res+=Math.max(leftMax-arr[l],0);
                leftMax=Math.max(leftMax,arr[l]);
            }else {
                r--;
                res+=Math.max(rightMax-arr[r],0);
                rightMax=Math.max(rightMax,arr[r]);
            }
        }
        return res;
    }

    //max函数o（1）复杂度的队列，和滑动窗口很类似
    public static class MaxQueue{
        private Queue<Integer> queue=new LinkedList<>();
        private LinkedList<Integer> max=new LinkedList<>();

        public MaxQueue(){

        }
        public void offer(int x){
            queue.offer(x);
            while (!max.isEmpty()&&max.peekLast()<x)
                max.pollLast();
            max.offer(x);
        }

        public int poll(){
            Integer tmp = queue.poll();
            Integer tmp2 = max.peek();
            if (tmp==tmp2)
                max.poll();
            return tmp;
        }

        public int max(){
            return max.peek();
        }
    }

    public boolean isStraight(int[] nums) {
        Arrays.sort(nums);
        int zero=0;
        int gap=0;
        for (int i=0;i<nums.length-1;i++){
            if (nums[i]==nums[i+1]&&nums[i]!=0)
                return false;
            else if (nums[i]==0)
                zero++;
            else
                gap+=(nums[i+1]-nums[i]-1);
        }
        return zero-gap>=0;

    }

    public int lastRemaining(int n, int m) {
        if (n==1)
            return 0;
        int pre=0;
        for (int i=2;i<=n;i++){
            pre=(pre+m)%n;
        }
        return pre;
    }

    public double[] dicesProbability(int n) {
        double[] dp=new double[6];
        Arrays.fill(dp,1.0/6.0);
        for (int i=2;i<=n;i++){
            double[] tmp=new double[5*i+1];
            for (int j=0;j<dp.length;j++){
                for (int k=0;k<6;k++){
                    tmp[j+k]=dp[j]/6.0;
                }
            }
            dp=tmp;
        }
        return dp;
    }

    public String longestCommonPrefix (String[] strs) {
        // write code here
        if (strs==null||strs.length==0)
            return "";
        String s=strs[0];
        for (int i=1;i<strs.length;i++){
            String tmp = getCommon(s, strs[i]);
            if (tmp=="")
                return "";
            else
                s=tmp;
        }
        return s;
    }

    public String getCommon(String s1,String s2){
        int bount=s1.length()<s2.length()?s1.length():s2.length();
        int index=0;
        while (index<bount&&s1.charAt(index)==s2.charAt(index))
            index++;
        return s1.substring(0,index);
    }

    //判断ipv4/ipv6
    public String solve33 (String IP) {
        // write code here
        if (isV4(IP))
            return "IPv4";
        else if (isV6(IP))
            return "IPv6";
        else
            return "Neither";
    }
    public boolean isV4(String ip){
        if (ip.indexOf('.')==-1)
            return false;
        String[] split = ip.split("\\.");
        if (split.length!=4)
            return false;
        for (int i=0;i<split.length;i++){
            String tmp=split[i];
            if (tmp.length()==0||tmp.length()>3)
                return false;
            if (tmp.charAt(0)=='0'&&tmp.length()>1)
                return false;
            int num=0;
            for (int j=0;j<tmp.length();j++){
                char c = tmp.charAt(j);
                if (c<'0'||c>'9')
                    return false;
                num=num*10+c-'0';
            }
            if (num<0||num>255)
                return false;
        }
        return true;
    }
    public boolean isV6(String ip){
        if (ip.indexOf(":")==-1)
            return false;
        String[] split = ip.split(":");
        if (split.length!=8)
            return false;
        for (int i=0;i<split.length;i++){
            String tmp = split[i];
            if (tmp.length()==0||tmp.length()>4)
                return false;
            if (tmp.charAt(0)=='0'&&tmp.length()>1)
                return false;
            for (int j=0;j<tmp.length();j++) {
                char c = tmp.charAt(j);
                if (!((c>='1'&&c<='9')||(c>='a'&&c<='f')||(c>='A'&&c<='F')))
                    return false;
            }
        }
        return true;
    }

    public String solve88 (String s, String t) {
        // write code here
        if (s.length()==0&&t.length()!=0)
            return t;
        if (s.length()!=0&&t.length()==0)
            return s;
        int sindex=s.length()-1;
        int tindex=t.length()-1;
        StringBuilder res=new StringBuilder();
        int cur=0;
        int add=0;
        while (sindex>=0&&tindex>=0){
            int si = s.charAt(sindex)-'0';
            int ti = t.charAt(tindex)-'0';
            cur=si+ti+add<=9?si+ti+add:si+ti+add-10;
            add=si+ti+add<=9?0:1;
            res.insert(0,cur);
            sindex--;
            tindex--;
        }
        while (sindex>=0){
            int si = s.charAt(sindex)-'0';
            cur=si+add<=9?si+add:si+add-10;
            add=si+add<=9?0:1;
            res.insert(0,cur);
            sindex--;
        }
        while (tindex>=0){
            int ti = t.charAt(tindex)-'0';
            cur=ti+add<=9?ti+add:ti+add-10;
            add=ti+add<=9?0:1;
            res.insert(0,cur);
            tindex--;
        }
        if (add!=0)
            res.insert(0,1);
        return res.toString();
    }

    public void merge(int A[], int m, int B[], int n) {
        int p1=m-1;
        int p2=n-1;
        int index=m+n-1;
        while (p1>=0&&p2>=0)
            A[index--]=A[p1]>=B[p2]?A[p1--]:B[p2--];
        while (p2>=0)
            A[index--]=B[p2--];
        return;
    }

    public class Interval {
      int start;
      int end;
      Interval() { start = 0; end = 0; }
      Interval(int s, int e) { start = s; end = e; }
  }

    public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
        ArrayList<Interval> res=new ArrayList<>();
        if (intervals==null||intervals.size()==0)
            return res;
        //sort by start
        Collections.sort(intervals, Comparator.comparingInt(i -> i.start));
        Interval pre=intervals.get(0);
        for (int i=1;i<intervals.size();i++){
            Interval interval = intervals.get(i);
            if (pre.end>=interval.start) {
                intervals.set(i, new Interval(pre.start, Math.max(pre.end, interval.end)));
                pre=intervals.get(i);
            }
            else
                res.add(pre);
        }
        res.add(intervals.get(intervals.size()-1));
        return res;
    }

    public String solve_reverse (String str) {
        // write code here
        if (str==null||str.length()==0)
            return str;
        return rev(str);
    }
    public String rev(String str){
        if (str.length()==1)
            return str;
        String substring = str.substring(1,str.length());
        return rev(substring)+str.charAt(0);
    }

    public String solve55(String str){
        int l=0;
        int r=str.length()-1;
        char[] chars = str.toCharArray();
        while (l<r){
            char tmp=chars[l];
            chars[l]=chars[r];
            chars[r]=tmp;
            l++;
            r--;
        }
        return new String(chars);
    }

    public int maxArea (int[] height) {
        // write code here
        if(height==null||height.length<2)
            return 0;
        int l=0;
        int r= height.length-1;
        int max=Integer.MIN_VALUE;
        while (l<r){
            int index= height[l]<= height[r]?l:r;
            max=Math.max(max,(r-l)* height[index]);
            if (index==l)
                l++;
            else
                r--;
        }
        return max;
    }

    public String minWindow (String S, String T) {
        // write code here
        if (S==null||T==null||S.length()==0||T.length()==0||S.length()<T.length())
            return "";
        int[] need=new int[128];
        int[] own=new int[128];
        for (int i=0;i<T.length();i++)
            need[T.charAt(i)]++;
        int count=0;
        int l=0;
        int r=0;
        int start=0;
        int minLen=Integer.MAX_VALUE;
        while (r<S.length()){
            char c = S.charAt(r);
            if (need[c]==0){
                r++;
                continue;
            }
            if (own[c]<need[c])
                count++;
            own[c]++;
            r++;
            while (count==T.length()){
                if (r-l<minLen){
                    minLen=r-l;
                    start=l;
                }
                char tmp= S.charAt(l);
                if (need[tmp]==0){
                    l++;
                    continue;
                }
                if (need[tmp]==own[tmp])
                    count--;
                own[tmp]--;
                l++;
            }
        }
        if (minLen==Integer.MAX_VALUE)
            return "";
        return S.substring(start,start+minLen);
    }

    public ListNode EntryNodeOfLoop2(ListNode pHead) {
        if (pHead==null||pHead.next==null||pHead.next.next==null)
            return null;
        ListNode fast=pHead.next.next;
        ListNode slow=pHead.next;
        while (fast!=slow){
            if (slow==null||fast==null||fast.next==null)
                return null;
            slow=slow.next;
            fast= fast.next.next;
        }
        if (fast==null||slow==null)
            return null;
        ListNode tmp=pHead;
        while (pHead!=fast){
            pHead=pHead.next;
            fast=fast.next;
        }
        return pHead;
    }

    public int candy (int[] arr) {
        // write code here
        if (arr.length==1)
            return 1;
        int[] res=new int[arr.length];
        Arrays.fill(res,1);
        for (int i=1;i<arr.length;i++){
            if (arr[i]>arr[i-1])
                arr[i]=arr[i-1]+1;
        }
        int count=res[arr.length-1];
        for (int i=arr.length-2;i>=0;i--){
            if (arr[i]>arr[i+1]&&res[i]<res[i+1])
                arr[i]=arr[i+1]+1;
            count+=arr[i];
        }
        return count;
    }

    public int minmumNumberOfHost (int n, int[][] startEnd) {
        // write code here
        int[] start=new int[n];
        int[] end=new int[n];
        for (int i=0;i<n;i++){
            start[i]=startEnd[i][0];
            end[i]=startEnd[i][1];
        }
        Arrays.sort(start);
        Arrays.sort(end);
        int count=0;
        int j=0;
        for(int i=0;i<start.length;i++){
            if (start[i]>=end[j])
                j++;
            else
                count++;
        }
        return count;
    }

    class LISnode{
        int len;
        int val;

        LISnode(int len,int val){
            this.len=len;
            this.val=val;
        }
    }
    public int lengthOfLIS(int[] nums) {
        if (nums.length==1)
            return 1;
        PriorityQueue<LISnode> priorityQueue=new PriorityQueue<LISnode>((node1,node2)->{
            if (node1.len==node2.len)
                return node1.val- node2.val;
            else
                return node2.len-node1.len;
        });
        priorityQueue.offer(new LISnode(1,nums[0]));
        for (int i=1;i<nums.length;i++){
            int j=0;
            Iterator<LISnode> iterator = priorityQueue.iterator();
            int flag=1;
            while (iterator.hasNext()){
                LISnode node= iterator.next();
                if (node.val<nums[i]){
                    LISnode tmp=new LISnode(node.len+1,nums[i]);
                    priorityQueue.offer(tmp);
                    flag=0;
                    break;
                }
            }
            if (flag==1){
                priorityQueue.offer(new LISnode(1,nums[i]));
            }
        }
        return priorityQueue.peek().len;
    }
    public int lengthOfLIS2(int[] nums) {
        int max=0;
        int[] tmp=new int[nums.length];
        for (int i=0;i<nums.length;i++){
            int l=0;
            int r=max;
            while (l<r){
                int mid=(r-l)/2+l;
                if (tmp[mid]<nums[i])
                    l=mid+1;
                else
                    r=mid;
            }
            tmp[l]=nums[i];
            if (l==max)
                max++;
        }
        return max;
    }

    public int[] solve (int n, int m, int[] a) {
        // write code here
        m=m%n;
        reverse22(a,0,n-1);
        reverse22(a,0,m-1);
        reverse22(a,m,n-1);
        return a;
    }
    public void reverse22(int[] arr,int start,int end){
        while (start<end){
            int tmp=arr[start]^arr[end];
            arr[start]=tmp^arr[start];
            arr[end]=tmp^arr[end];
            start++;
            end--;
        }
    }


    public int[][] rotateMatrix(int[][] mat, int n) {
        // write code here
        int x1=0;
        int x2=mat.length-1;
        while (x1<x2)
            rotate(mat,x1++,x2--);
        return mat;
    }
    public void rotate(int[][] mat,int x1,int x2){
        int groupCount=x2-x1;
        for (int i=0;i<groupCount;i++)
            rotateByGroup(mat,x1,x2,i);
    }
    public void rotateByGroup(int[][] mat,int x1,int x2,int i){
        int tmp1=mat[x1][x1+i];
        int tmp2=mat[x1+i][x2];
        int tmp3=mat[x2][x2-i];
        int tmp4=mat[x2-i][x1];
        mat[x1+i][x2]=tmp1;
        mat[x2][x2-i]=tmp2;
        mat[x2-i][x1]=tmp3;
        mat[x1][x1+i]=tmp4;
    }

    public int maxSubArray(int[] nums) {
        if (nums.length==1)
            return 1;
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        int max=dp[0];
        for (int i=1;i<nums.length;i++){
            dp[i]=Math.max(nums[i],dp[i-1]+nums[i]);
            max=Math.max(max,dp[i]);
        }
        return max;
    }


    HashMap<Integer,Integer> data=new HashMap<>();
    HashMap<Integer,Integer> indexs=new HashMap<>();
    LinkedList<Integer> lru=new LinkedList<>();
    int capacity;
    int currentSize;
    public void Solution(int capacity) {
        // write code here
        this.capacity=capacity;
    }

    public int get(int key) {
        // write code here
        if (data.containsKey(key)) {
            Integer index = indexs.get(key);
            lru.remove(index);
            lru.offer(key);
            indexs.put(key,lru.size()-1);
            return data.get(key);
        }
        else
            return -1;
    }

    public void set(int key, int value) {
        // write code here
        if (currentSize<capacity){
            data.put(key,value);
            lru.offer(key);
            indexs.put(key,lru.size()-1);
            currentSize++;
            return;
        }
        if (data.containsKey(key)){
            data.put(key,value);
            Integer index = indexs.get(key);
            lru.remove(index);
            lru.offer(key);
            indexs.put(key,lru.size()-1);
        }else {
            lru.poll();
            lru.offer(key);
            indexs.put(key,lru.size()-1);
            data.put(key,value);
        }
    }

    class LFUnode{
        int freq;
        int key;
        int val;

        public LFUnode(int freq,int key,int val){
            this.freq=freq;
            this.key=key;
            this.val=val;
        }
    }

    HashMap<Integer,LFUnode> LFUdata=new HashMap<>();
    HashMap<Integer,LinkedList<LFUnode>> freq=new HashMap<>();
    int k_lfu;
    int curk;
    int min_freq=Integer.MAX_VALUE;
    public int[] LFU (int[][] operators, int k) {
        // write code here
        k_lfu=k;
        curk=0;
        int len=0;
        for (int i=0;i<operators.length;i++){
            if (operators[i][0]==2)
                len++;
        }
        int[] res=new int[len];
        int index=0;
        for (int i=0;i<operators.length;i++){
            if (operators[i][0]==1){
                setLFU(operators[i][1],operators[i][2]);
            }else {
                int lfu = getLFU(operators[i][1]);
                res[index++]=lfu;
            }
        }
        return res;
    }
    public void setLFU(int key,int value){
        if (LFUdata.containsKey(key)){
            LFUdata.get(key).val=value;
            LFUdata.get(key).freq++;
            update(LFUdata.get(key));
        }else {
            if (curk < k_lfu) {
                LFUnode lfUnode = new LFUnode(1, key, value);
                LFUdata.put(key, lfUnode);
                LinkedList<LFUnode> lfUnodes = freq.get(1);
                if (lfUnodes==null){
                    lfUnodes=new LinkedList<>();
                    lfUnodes.offer(lfUnode);
                    freq.put(1,lfUnodes);
                }else {
                    lfUnodes.offer(lfUnode);
                }
                curk++;
                min_freq=Math.min(min_freq,1);
            } else {
                LinkedList<LFUnode> lfUnodes = freq.get(min_freq);
                LFUnode pollnode = lfUnodes.poll();
                LFUdata.remove(pollnode.key);
                if (lfUnodes.isEmpty())
                    freq.put(min_freq,null);
                LFUnode lfUnode = new LFUnode(1, key, value);
                LFUdata.put(key, lfUnode);
                LinkedList<LFUnode> lfUnodes2 = freq.get(1);
                if (lfUnodes2==null){
                    lfUnodes2=new LinkedList<>();
                    lfUnodes2.offer(lfUnode);
                    freq.put(1,lfUnodes2);
                }else {
                    lfUnodes2.offer(lfUnode);
                }
                min_freq=Math.min(min_freq,1);
            }
        }
    }
    public int getLFU(int key){
        if (LFUdata.containsKey(key)){
            LFUnode lfUnode = LFUdata.get(key);
            lfUnode.freq++;
            update(lfUnode);
            return lfUnode.val;
        }
        return -1;
    }
    public void update(LFUnode node){
        LinkedList<LFUnode> lfUnodes = freq.get(node.freq - 1);
        lfUnodes.remove(node);
        if (lfUnodes.isEmpty())
            freq.put(node.freq-1,null);
        while (freq.get(min_freq)==null)
            min_freq++;
        LinkedList<LFUnode> lfUnodes1 = freq.get(node.freq);
        if (lfUnodes1==null) {
            lfUnodes1 = new LinkedList<>();
            freq.put(node.freq,lfUnodes1);
        }
        lfUnodes1.offer(node);
    }

    public int maxProfit_tanxin(int[] prices){
        if(prices.length<2)
            return 0;
        int premin=prices[0];
        int maxProfit=Integer.MIN_VALUE;
        for (int i=1;i< prices.length;i++){
            maxProfit=Math.max(maxProfit,prices[i]-premin);
            premin=Math.min(premin,prices[i]);
        }
        return maxProfit>0?maxProfit:-1;
    }

    public int add(int a, int b) {
        int add=a&b;
        int cur=a^b;
        while (add!=0){
            int tmp=add<<1;
            cur=cur^tmp;
            add=cur&tmp;
        }
        return cur;
    }

    //leetcode热题
    //三数之和

    public List<List<Integer>> threeSum_leetcode(int[] nums) {
        ArrayList<List<Integer>> res=new ArrayList<>();
        if (nums.length<3)
            return res;
        Arrays.sort(nums);
        for (int i=0;i<nums.length-2;i++){
            if (nums[i]>0)
                break;
            if (i!=0&&nums[i]==nums[i-1])
                continue;
            int target=0-nums[i];
            int m=i+1;
            int n=nums.length-1;
            while (m<n){
                int cur=nums[m]+nums[n];
                if (cur==target){
                    List<Integer> list=new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[m]);
                    list.add(nums[n]);
                    res.add(list);
                }else if (cur<target){
                    m++;
                }else
                    n--;
                while (m<nums.length&&nums[m]==nums[m-1]) m++;
                while (nums[n]==nums[n+1]) n--;
            }
        }
        return res;
    }

    //17
    String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    public List<String> letterCombinations(String digits) {
        ArrayList<String> res = new ArrayList<>();
        if (digits == null || digits.length() == 0)
            return res;
        process4generate(0,"",digits,res);
        return res;
    }
    public void process4generate(int index,String pre,String digits,List<String> res){
        if (index==digits.length()){
                res.add(pre);
                return;
        }
        char c = digits.charAt(index++);
        int num=c-'0';
        String s = numString[num];
        for (int i=0;i<s.length();i++){
            process4generate(index,pre+s.charAt(i),digits,res);
        }
    }

    //22
    public List<String> generateParenthesis4(int n) {
            List<String> res=new ArrayList<>();
            if (n==1)
                return res;
            generate(0,0,n,res,"");
            return res;
    }
    public void generate(int l,int r,int n,List<String> res,String pre){
        if (l>n||r>n)
            return;
        if (l==n&&r==n)
            res.add(pre);
        if (l>=r){
            if (l==n)
                generate(l,r+1,n,res,pre+')');
            else {
                generate(l+1,r,n,res,pre+'(');
                generate(l,r+1,n,res,pre+')');
            }
        }
    }

    //下一个排列
    public void nextPermutation(int[] nums) {
        int start=0;
        for (int i=nums.length-1;i>=0;i--){
            if (i>0&&nums[i]>nums[i-1]){
                start=i;
                break;
            }
        }
        if (start==0){
            reverse_arr(nums,start,nums.length-1);
            return;
        }
        reverse_arr(nums,start,nums.length-1);
        int change=start-1;
        for (int i=start;i<nums.length;i++){
            if (nums[i]>nums[change]){
                int tmp=nums[change];
                nums[change]=nums[i];
                nums[i]=tmp;
                return;
            }
        }
    }
    public void reverse_arr(int[] nums,int start,int end){
        while (start<end){
            int tmp=nums[start];
            nums[start]=nums[end];
            nums[end]=tmp;
            start++;
            end--;
        }
    }

    public int search44(int[] nums, int target) {
        if (nums.length==0)
            return -1;
        int left=0;
        int right=nums.length-1;
        while (left<=right){
            int mid=left+(right-left)/2;
            if (nums[mid]==target)
                return mid;
            if (nums[mid]<nums[right]){
                if (nums[mid]<target&&target<=nums[right])
                    left=mid+1;
                else
                    right=mid-1;
            }else {
                if (nums[mid]>target&&target>=nums[left])
                    right=mid-1;
                else
                    left=mid+1;
            }
        }
        return -1;
    }

    //有序数组中查找target的范围下标
    public int[] searchRange(int[] nums, int target) {
            if (nums.length==0)
                return new int[]{-1,-1};
            int left=-1;
            int i=0;
            int j=nums.length-1;
            while (i<=j){
                int mid=i+(j-i)/2;
                if (nums[mid]==target) {
                    if (mid==0||(mid>0&&nums[mid]!=nums[mid-1])){
                        left=mid;
                        break;
                    }
                    j=mid-1;
                }
                else if(nums[mid]<target)
                    i=mid+1;
                else
                    j=mid-1;
            }
            int right=-1;
            i=0;
            j=nums.length-1;
            while (i<=j){
                int mid=i+(j-i)/2;
                if (nums[mid]==target) {
                    if (mid==nums.length-1||(mid<nums.length-1&&nums[mid]!=nums[mid+1])){
                    right=mid;
                    break;
                    }
                i=mid+1;
              }
            else if(nums[mid]<target)
                i=mid+1;
            else
                j=mid-1;
           }
            return new int[]{left,right};
    }

    //39

    List<List<Integer>> res4com =new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        int index=candidates.length-1;
        int i=0;
        int j=candidates.length-1;
        while (i<=j){
            int mid=i+(j-i)/2;
            if (candidates[mid]==target){
                index=mid;
                break;
            }else if (candidates[mid]>target){
                if (mid==0||(mid>0&&candidates[mid-1]<target)){
                    index=mid;
                    break;
                }
                j=mid-1;
            }else {
                i=mid+1;
            }
        }
        int[] tmp = Arrays.copyOfRange(candidates, 0, candidates[index] <= target ? index + 1 : index);
        if (tmp.length==0)
            return res4com;
        process4com(tmp,0,target,new ArrayList<>());
        return res4com;
    }
    public void process4com(int[] arr,int index,int target,List<Integer> tmp){
        if (target==0) {
            res4com.add(new ArrayList<>(tmp));
            return;
        }
        if (index>=arr.length)
            return;
        int count=0;
        int tmp_num=arr[index];
        while (tmp_num<=target){
            count++;
            tmp_num+=arr[index];
        }
        int orign_target=target;
        for (int i=0;i<=count;i++){
            for (int j=0;j<i;j++){
                tmp.add(arr[index]);
                target-=arr[index];
            }
            process4com(arr,index+1,target,tmp);
            for (int j=0;j<i;j++){
                tmp.remove(tmp.size()-1);
            }
            target=orign_target;
        }
    }


    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue<ListNode> priorityQueue=new PriorityQueue<ListNode>((node1,node2)->{
            return node1.val-node2.val;
        });
        for (ListNode node:lists) {
            if(node!=null)
                priorityQueue.offer(node);
        }
        ListNode head=new ListNode(0);
        ListNode end=head;
        while (!priorityQueue.isEmpty()){
            ListNode tmp= priorityQueue.poll();
            end.next=tmp;
            end=tmp;
            if (tmp.next!=null)
                priorityQueue.offer(tmp.next);
        }
        return head.next;
    }

    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String,ArrayList<String>> map=new HashMap<>();
        for (String s:strs){
            char[] chars = s.toCharArray();
            Arrays.sort(chars);
            String sorted_s = String.valueOf(chars);
            if (!map.containsKey(sorted_s)) map.put(sorted_s,new ArrayList<>());
            map.get(sorted_s).add(s);
        }
        return new ArrayList<>(map.values());
    }

    //重新写一遍，39
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res=new LinkedList<>();
        Arrays.sort(candidates);
        backtrace4com(candidates,0,0,target,new ArrayList<>(),res);
        return res;
    }
    public void backtrace4com(int[] arr,int index,int cur,int target,ArrayList<Integer> path,List<List<Integer>> res
    ){
        if (cur==target){
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i=index;i<arr.length;i++){
            if (cur+arr[i]>target)
                break;
            path.add(arr[i]);
            backtrace4com(arr,index,cur+arr[i],target,path,res);
            path.remove(path.size()-1);
        }
    }

    //56
    public class interval{
        int start;
        int end;

        public interval(int s,int e){
            this.start=s;
            this.end=e;
        }
    }

    public int[][] merge(int[][] intervals) {
        PriorityQueue<interval> priorityQueue=new PriorityQueue<interval>((i1,i2)->{
            if (i1.start==i2.start)
                return i1.end-i2.end;
            else
                return i1.start-i2.start;
        });
        for (int i=0;i<intervals.length;i++){
            interval tmp=new interval(intervals[i][0],intervals[i][1]);
            priorityQueue.offer(tmp);
        }
        ArrayList<interval> res=new ArrayList<>();
        while (!priorityQueue.isEmpty()){
            interval poll = priorityQueue.poll();
            while (!priorityQueue.isEmpty()&&poll.end>=priorityQueue.peek().start){
                interval poll2 = priorityQueue.poll();
                poll.end=Math.max(poll2.end,poll.end);
            }
            res.add(poll);
        }
        int[][] res_arr=new int[res.size()][2];
        for (int i=0;i< res_arr.length;i++){
            res_arr[i][0]=res.get(i).start;
            res_arr[i][1]=res.get(i).end;
        }
        return res_arr;
    }

    //62
    public int uniquePaths62(int m, int n) {
        int[][] dp=new int[m][n];
        for (int i=0;i<m;i++)
            dp[i][0]=1;
        for (int i=0;i<n;i++)
            dp[0][i]=1;
        for (int i=1;i<m;i++){
            for (int j=1;j<n;j++){
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }

    //64
    public int minPathSum64(int[][] grid) {
        int[][] dp=new int[grid.length][grid[0].length];
        dp[0][0]=grid[0][0];
        for (int i=1;i<dp.length;i++)
            dp[i][0]=dp[i-1][0]+ grid[i][0];
        for (int j=1;j<dp[0].length;j++)
            dp[0][j]=dp[0][j-1]+ grid[0][j];
        for (int i=1;i<dp.length;i++){
            for (int j=1;j<dp[0].length;j++){
                dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1])+grid[i][j];
            }
        }
        return dp[grid.length-1][grid[0].length-1];
    }

    //75 三色国旗问题
    public void sortColors(int[] nums) {
        int lbound=-1;
        int rbound=nums.length;
        int i=0;
        while (i<rbound){
            if (nums[i]==0){
                lbound++;
                swap4color(nums,i,lbound);
                if (i==lbound)
                    i++;
            }else if (nums[i]==2){
                rbound--;
                swap4color(nums,i,rbound);
            }else
                i++;
        }
    }
    public void swap4color(int[] nums,int i,int j){
        int tmp=nums[i];
        nums[i]=nums[j];
        nums[j]=tmp;
    }

    //79
    boolean existflag=false;
    public boolean exist_(char[][] board, String word) {
        boolean[][] visited=new boolean[board.length][board[0].length];
        for (int i=0;i< board.length;i++){
            for (int j=0;j<board[0].length;j++){
                if (board[i][j]==word.charAt(0))
                    bt4exist(board,i,j,0,word,visited);
                if (existflag==true)
                    return true;
            }
        }
        return existflag;
    }
    public void bt4exist(char[][] board,int x,int y,int index,String target,boolean[][] visited){
        if (x<0||x>= board.length||y<0||y>=board[0].length||visited[x][y]==true)
            return;

        if (index==target.length()){
            existflag=true;
            return;
        }
        if (board[x][y]!=target.charAt(index))
            return;
        visited[x][y]=true;

        bt4exist(board,x+1,y,index+1,target,visited);
        bt4exist(board,x-1,y,index+1,target,visited);
        bt4exist(board,x,y+1,index+1,target,visited);
        bt4exist(board,x,y-1,index+1,target,visited);

        visited[x][y]=false;
    }

    //94 ez题
    public List<Integer> inorderTraversal2(TreeNode root) {
            List<Integer> res=new ArrayList<>();
            inorder(root,res);
            return res;
    }
    public void inorder(TreeNode node,List<Integer> res){
        if(node==null)
            return;;
        inorder(node.left,res);
        res.add(node.val);
        inorder(node.right,res);
    }

    //96
    public int numTrees(int n) {
        int[] dp=new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for (int i=2;i<=n;i++){
            for (int j=1;j<=i;j++){
                dp[i]+=dp[j-1]*dp[i-j];
            }
        }
        return dp[n];
    }

    //98
    private TreeNode pre=null;
    private boolean flag4bst=true;
    public boolean isValidBST_(TreeNode root) {
        inorfer4bst(root);
        return flag4bst;
    }
    public void inorfer4bst(TreeNode node){
        if (node==null)
            return;
        inorfer4bst(node.left);
        if (pre==null)
            pre=node;
        else {
            if (pre.val>node.val){
                flag4bst=false;
                return;
            }else
                pre=node;
        }
        inorfer4bst(node.right);
    }

    //101
    public boolean isSymmetric_(TreeNode root) {
        return traverse4sym(root.left,root.right);
    }
    public boolean traverse4sym(TreeNode node1,TreeNode node2){
        if (node1==null&&node2==null)
            return true;
        if (node1==null&&node2!=null)
            return false;
        if (node1!=null&&node2==null)
            return false;
        if (node1.val!=node2.val)
            return false;
        return traverse4sym(node1.left,node2.right)&&traverse4sym(node1.right,node2.left);
    }

    //102
    public List<List<Integer>> levelOrder5(TreeNode root) {
            ArrayList<List<Integer>> res=new ArrayList<List<Integer>>();
            LinkedList<TreeNode> queue=new LinkedList();
            queue.offer(root);
            while (!queue.isEmpty()){
                int size = queue.size();
                ArrayList<Integer> tmp=new ArrayList<>();
                while (size-->0){
                    TreeNode poll = queue.poll();
                    tmp.add(poll.val);
                    if (poll.left!=null)
                        queue.offer(poll.left);
                    if (poll.right!=null)
                        queue.offer(poll.right);
                }
            }
            return res;
    }

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length==0)
            return null;
        int root= preorder[0];
        int index=0;
        for (int i=0;i<inorder.length;i++){
            if (inorder[i]==root){
                index=i;
            }
        }
        int[] lp = Arrays.copyOfRange(preorder, 1, 1+index);
        int[] rp=Arrays.copyOfRange(preorder,index+1,preorder.length);
        int[] li=Arrays.copyOfRange(inorder,0,index);
        int[] ri=Arrays.copyOfRange(inorder,1+index,inorder.length);
        TreeNode lroot = buildTree(lp, li);
        TreeNode rrott=buildTree(rp,ri);
        TreeNode res=new TreeNode(preorder[0]) ;
        res.left=lroot;
        res.right=rrott;
        return res;
    }

    //114二叉树转换成链表，这个题题解很秀！一定要看！
    private class flattenData{
        TreeNode start;
        TreeNode end;

        public  flattenData(TreeNode s,TreeNode e){
            this.start=s;
            this.end=e;
        }
    }
    public void flatten1(TreeNode root) {
            flat(root);
    }
    public flattenData flat(TreeNode node){
        if (node==null)
            return null;
        flattenData ldata = flat(node.left);
        flattenData rdata = flat(node.right);
        node.left=null;
        if (ldata==null&&rdata==null)
            return new flattenData(node,node);
        if (ldata!=null&&rdata==null){
            node.right= ldata.start;
            return new flattenData(node, ldata.end);
        }
        if (ldata==null&&rdata!=null){
            node.right=rdata.start;
            return new flattenData(node, rdata.end);
        }
        node.right= ldata.start;
        ldata.end.right=rdata.start;
        return new flattenData(node,rdata.end);
    }

    public void flatten2(TreeNode root) {
        while (root!=null){
            if (root.left==null){
                root=root.right;
                continue;
            }else {
                TreeNode pre=root.left;
                while (pre.right!=null)
                    pre=pre.right;
                pre.right=root.right;
                root.right=root.left;
                root.left=null;
                root=root.right;
            }
        }
    }


    public TreeNode backwardflat;
    public void flatten(TreeNode root) {
        if (root==null)
            return;
        flatten(root.right);
        flatten(root.left);
        if (backwardflat==null)
            backwardflat=root;
        else {
            root.right=backwardflat;
            root.left=null;
            backwardflat=root;
        }
    }

    //121
    public int maxProfit121(int[] prices) {
            if (prices.length==1)
                return 0;
            int premin=prices[0];
            int maxprofit=Integer.MIN_VALUE;
            for (int i=1;i< prices.length;i++){
                maxprofit=Math.max(maxprofit,prices[i]-premin);
                premin=Math.min(premin,prices[i]);
            }
            return maxprofit<0?0:maxprofit;
    }

    //128
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> set=new HashSet<>();
        for (int num:nums)
            set.add(num);
        int maxlen=Integer.MIN_VALUE;
        for (int i=0;i<nums.length;i++){
            if (set.contains(nums[i]-1))
                continue;
            else {
                int count=0;
                int base=nums[i];
                while (set.contains(base)){
                    count++;
                    base++;
                }
                maxlen=Math.max(maxlen,count);
            }
        }
        return maxlen;
    }

    //3

    public boolean verifyPostorder(int[] postorder) {
        if(postorder.length<=1)
            return true;
        int root_val=postorder[postorder.length-1];
        int index=-1;
        for (int i=postorder.length-1;i>=0;i--){
            if (postorder[i]<root_val){
                index=i;
                break;
            }
        }
        for (int i=0;i<index;i++){
            if (postorder[i]>root_val)
                return false;
        }
        int[] l = Arrays.copyOfRange(postorder, 0, index + 1);
        int[] r=Arrays.copyOfRange(postorder,index+1,postorder.length-1);
        return verifyPostorder(l)&&verifyPostorder(r);
    }

    public int countNodes(TreeNode node){
        if (node==null)
            return 0;
        return countNodesHelp(node,1,getLevel(node,1));
    }
    public int countNodesHelp(TreeNode node,int curlevel,int totallevel){
        if (curlevel==totallevel)
            return 1;
        if (getLevel(node.right,curlevel+1)==totallevel)
            return (1<<(totallevel-curlevel))+countNodesHelp(node.right,curlevel+1,totallevel);
        else
            return (1<<(totallevel-curlevel-1))+countNodesHelp(node.left,curlevel+1,totallevel);
    }
    //只适用于完全二叉树
    public int getLevel(TreeNode node,int curlevel){
        while (node!=null){
            curlevel++;
            node=node.left;
        }
        return curlevel-1;
    }
    public int lengthOfLIS3(int[] nums) {
        if(nums.length==1)
            return 1;
        int[] ends=new int[nums.length];
        ends[0]=nums[0];
        int bound=0;
        for(int i=1;i<nums.length;i++){
            if(nums[i]==ends[bound])
                continue;
            if(nums[i]>ends[bound]){
                bound++;
                ends[bound]=nums[i];
                continue;
            }
            int left=0;
            int right=bound;
            while(left<right){
                int mid=left+(right-left)/2;
                if(ends[mid]<nums[i])
                    left=mid+1;
                else
                    right=mid;
            }
            ends[left]=nums[i];
        }
        return bound+1;
    }

    public int longestConsecutive2(int[] nums) {
        if (nums.length==0)
            return 0;
        HashSet<Integer> set=new HashSet<>();
        for (int num:nums)
            set.add(num);
        int res=0;
        for (int i=0;i<nums.length;i++){
            int tmp=nums[i];
            if (set.contains(nums[i-1]))
                continue;
            else {
                int count=0;
                while (set.contains(tmp)){
                    count++;
                    tmp++;
                }
                res=Math.max(res,count);
            }
        }
        return res;
    }

    public boolean hasCycle2(ListNode head) {
        if (head==null||head.next==null||head.next.next==null)
            return false;
        ListNode slow=head.next;
        ListNode fast=head.next.next;
        while (slow!=fast){
            if (slow==null||fast.next==null)
                return false;
            slow=slow.next;
            fast=fast.next.next;
        }
        return true;
    }

    //139单词拆分，这个回溯不对，看下面的dp，这个题要好好看看
    private boolean flag4word=false;
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> data=new HashSet<>();
        for (int i=0;i<wordDict.size();i++)
            data.add(wordDict.get(i));
        help4word(s,0,data);
        return flag4word;
    }
    public void help4word(String s,int index,HashSet<String> data){
        if (index==s.length()){
            flag4word=true;
            return;
        }
        StringBuilder sb=new StringBuilder();
        for (int i=index;i<s.length();i++){
            sb.append(s.charAt(i));
            if (data.contains(sb.toString())){
                help4word(s,i+1,data);
            }
        }
    }

    public boolean wordBreak_dp(String s, List<String> wordDict) {
        HashSet<String> data=new HashSet<>();
        for (int i=0;i<wordDict.size();i++)
            data.add(wordDict.get(i));
        boolean[] dp=new boolean[s.length()+1];
        dp[0]=true;
        for (int i=1;i<dp.length;i++){
            for(int j=0;j<i;j++){
                if (dp[j]&&data.contains(s.substring(j,i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[dp.length-1];
    }

    //124
    public class helpData{
        int maxSum;
        TreeNode start;
        TreeNode end;
        public helpData(int max,TreeNode s,TreeNode e){
            this.maxSum=max;
            this.start=s;
            this.end=e;
        }
    }

    //142
    public ListNode detectCycle2(ListNode head) {
        if(head==null||head.next==null||head.next.next==null)
            return null;
        ListNode fast=head.next.next;
        ListNode slow=head.next;
        while (fast!=slow){
            if (slow==null||fast==null||fast.next==null)
                return null;
            slow=slow.next;
            fast=fast.next.next;
        }
        fast=head;
        while (fast!=slow){
            fast=fast.next;
            slow=slow.next;
        }
        return fast;
    }

    //148
    public ListNode sortList(ListNode head) {
        if (head==null)
            return null;
        return mergeSort_list(head);
    }
    public ListNode mergeSort_list(ListNode node){
        if (node==null)
            return null;
        if (node.next==null)
            return node;
        ListNode dummy=new ListNode(-1);
        dummy.next=node;
        ListNode fast=dummy.next.next;
        ListNode slow=dummy.next;
        while (fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        ListNode list2=slow.next;
        slow.next=null;
        dummy.next=null;
        ListNode l1 = mergeSort_list(node);
        ListNode l2 = mergeSort_list(list2);
        ListNode res = merge_list(l1, l2);
        return res;
    }
    public ListNode merge_list(ListNode l1,ListNode l2){
        ListNode dummy=new ListNode(-1);
        ListNode pre=dummy;
        while (l1!=null&&l2!=null){
            if (l1.val<l2.val){
                pre.next=l1;
                pre=l1;
                l1=l1.next;
            }else {
                pre.next=l2;
                pre=l2;
                l2=l2.next;
            }
        }
        while (l1!=null){
            pre.next=l1;
            pre=l1;
            l1=l1.next;
        }
        while (l2!=null){
            pre.next=l2;
            pre=l2;
            l2=l2.next;
        }
        return dummy.next;
    }

    //152
    public int maxProduct2(int[] nums) {
        if(nums.length==1)
            return nums[0];
        int[] dp=new int[nums.length];
        int[] dp_min=new int[nums.length];
        dp[0]=dp_min[0]=nums[0];
        int res=dp[0];
        for (int i=0;i<nums.length;i++){
            dp[i]=Math.max(nums[i],Math.max(dp[i-1]*nums[i],dp_min[i-1]*nums[i]));
            dp_min[i]=Math.min(nums[i],Math.min(dp[i-1]*nums[i],dp_min[i-1]*nums[i]));
            res=Math.max(res,dp[i]);
        }
        return res;
    }

    //221
    public int maximalSquare2(char[][] matrix) {
        int[][] rightone=new int[matrix.length][matrix[0].length];
        for (int i=0;i<rightone.length;i++)
            rightone[i][rightone[0].length-1]=matrix[i][rightone[0].length-1]=='1'?1:0;
        for (int i=0;i<rightone.length;i++){
            for (int j=rightone[0].length-2;j>=0;j--){
                if (matrix[i][j]=='0')
                    rightone[i][j]=0;
                else
                    rightone[i][j]=rightone[i][j+1]+1;
            }
        }
        int[][] downone=new int[matrix.length][matrix[0].length];
        for (int j=0;j< downone[0].length;j++)
            downone[downone.length-1][j]=matrix[downone.length-1][j]=='1'?1:0;
        for (int j=0;j< downone[0].length;j++){
            for (int i= downone.length-2;i>=0;i--){
                if (matrix[i][j]=='0')
                    downone[i][j]=0;
                else
                    downone[i][j]=downone[i+1][j]+1;
            }
        }
        int max_edge=0;
        for (int i=0;i< matrix.length;i++){
            for (int j=0;j< matrix[0].length;j++){
                if (matrix[i][j]=='1'){
                    int tmp=Math.min(downone[i][j],rightone[i][j]);
                    int flag=1;
                    for (int x=j;x<j+tmp;x++){
                        if (downone[i][x]<tmp){
                            flag=0;
                            break;
                        }
                    }
                    for (int y=i;y<i+tmp;y++){
                        if (rightone[y][j]<tmp){
                            flag=0;
                            break;
                        }
                    }
                    if (flag==1){
                        max_edge=Math.max(max_edge,tmp);
                    }
                }
            }
        }
        return max_edge*max_edge;
    }

    //221
    public int maximalSquare(char[][] matrix) {
        int[][] dp=new int[matrix.length][matrix[0].length];
        int flag=0;
        for (int i=0;i<matrix.length;i++) {
            dp[i][0] = matrix[i][0] == '1' ? 1 : 0;
            if (matrix[i][0]=='1')
                flag=1;
        }
        for(int j=0;j<matrix[0].length;j++) {
            dp[0][j] = matrix[0][j] == '1' ? 1 : 0;
            if (matrix[0][j]=='1')
                flag=1;
        }
        int max_edge=flag==1?1:0;
        for (int i=1;i<matrix.length;i++){
            for (int j=1;j<matrix[0].length;j++){
                if(matrix[i][j]=='1'){
                    dp[i][j]=1+Math.min(Math.min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]);
                    max_edge=Math.max(max_edge,dp[i][j]);
                }
            }
        }
        return max_edge*max_edge;
    }

    //234
    public boolean isPalindrome(ListNode head) {
        if (head==null||head.next==null)
            return true;
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode slow=head;
        ListNode fast=head.next;
        while (fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        ListNode pre=slow;
        ListNode cur=slow.next;
        slow.next=null;
        ListNode next;
        ListNode tail=null;
        while (cur!=null){
            if (cur.next==null)
                tail=cur;
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        while (head!=null&&head!=tail){
            if (head.val!=tail.val)
                return false;
            head=head.next;
            tail=tail.next;
        }
        return true;
    }

    //215
    public int findKthLargest(int[] nums, int k) {
        if (k>nums.length)
            return -1;
        return findkmin(nums,0,nums.length-1,k);
    }

    public int findkmin(int[] nums,int l ,int r,int k){
        int pos=paration4k(nums,l,r);
        int curkmin=pos-l+1;
        if(curkmin==k)
            return nums[curkmin];
        if (curkmin<k)
            return findkmin(nums,pos,r,k-curkmin);
        else
            return findkmin(nums,l,pos,k);
    }
    public int paration4k(int[] nums,int l,int r){
        int lbound=l-1;
        int base=nums[r];
        int index=l;
        while (index<r){
            if (nums[index]<base){
                lbound++;
                if (lbound!=index){
                    int tmp=nums[lbound];
                    nums[lbound]=nums[index];
                    nums[index]=tmp;
                }
            }
        }
        int pos=lbound+1;
        int tmp=nums[pos];
        nums[pos]=base;
        nums[r]=tmp;
        return pos;
    }

    //236
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if (root==p||root==q||root==null)
                return root;
        TreeNode lres = lowestCommonAncestor(root.left, p, q);
        TreeNode rres=lowestCommonAncestor(root.right,p,q);
        if (lres==null)
            return rres;
        if (rres==null)
            return lres;
        return root;
    }

    //207
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int len= prerequisites.length;
        int[] counts=new int[numCourses];
        Queue<int[]> records=new LinkedList<>();
        for (int[] arr:prerequisites){
            counts[arr[0]]++;
            records.offer(arr);
        }
        while (!records.isEmpty()){
            int size=records.size();
            for(int i=0;i<size;i++){
                int[] tmp = records.poll();
                if (counts[tmp[1]]==0)
                    counts[tmp[0]]--;
                else
                    records.offer(tmp);
            }
            if (records.size()==size)
                return false;
        }
        return true;
    }

    //238
    public int[] productExceptSelf(int[] nums) {
        if (nums.length==1)
            return new int[]{nums[0]};
        int[] left=new int[nums.length];
        left[0]=1;
        for (int i=1;i<nums.length;i++)
            left[i]=left[i-1]*nums[i-1];
        int[] right=new int[nums.length];
        right[nums.length-1]=1;
        for (int j=nums.length-2;j>=0;j--)
            right[j]=right[j+1]*nums[j+1];
        int[] res=new int[nums.length];
        for (int i=0;i<res.length;i++)
            res[i]=left[i]*right[i];
        return res;
    }

    //240
    public boolean searchMatrix(int[][] matrix, int target) {
        int x=0;
        int y=matrix[0].length-1;
        while (x<matrix.length&&y>=0){
            if (matrix[x][y]==target)
                return true;
            else if (matrix[x][y]<target)
                x++;
            else
                y--;
        }
        return false;
    }

    //279
    public int numSquares(int n) {
        int[] dp=new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            dp[i]=Integer.MAX_VALUE;
            for (int j=0;j*j<=i;j++){
                int tmp=dp[i-j*j];
                if (tmp!=Integer.MAX_VALUE)
                    dp[i]=Math.min(tmp+1,dp[i]);
            }
        }
        return dp[n];
    }

    //283
    public void moveZeroes(int[] nums) {
        int i=0;
        int j=0;
        while (i++<nums.length){
            if (nums[i]!=0)
                nums[j++]=nums[i];
        }
        while (j<nums.length)
            nums[j++]=0;
    }

    //287
    public int findDuplicate2(int[] nums) {
        for (int i=0;i<nums.length;i++){
            while (i+1!=nums[i]&&nums[nums[i]-1]!=nums[i]){
                int tmp=nums[nums[i]-1];
                nums[nums[i]-1]=nums[i];
                nums[i]=tmp;
            }
        }
        for (int i=0;i<nums.length;i++){
            if (nums[i]!=i+1)
                return nums[i];
        }
        return -1;
    }

    public int findDuplicate3(int[] nums) {
        for (int i=0;i<nums.length;i++){
            int num=Math.abs(nums[i]);
            if (nums[num-1]<0)
                return num;
            else
                nums[num-1]=-nums[num-1];
        }
        return -1;
    }

    public int findDuplicate4(int[] nums) {
        HashSet<Integer> set=new HashSet<>();
        int i=0;
        while (true){
            if(set.contains(nums[i]))
                return nums[i];
            else {
                set.add(nums[i]);
                i=nums[i];
            }
        }
    }

    public int findDuplicate(int[] nums) {
        int i=0;
        int j=0;
        do {
            i=nums[i];
            j=nums[nums[j]];
        }while (nums[i]!=nums[j]);
        i=0;
        while (nums[i]!=nums[j]){
            i=nums[i];
            j=nums[j];
        }
        return nums[i];
    }

    //239  滑动窗口的最大值
    public int[] maxSlidingWindow3(int[] nums, int k) {
        LinkedList<Integer> queue=new LinkedList<>();
        for(int i=0;i<k;i++){
            while (!queue.isEmpty()&&nums[queue.peekLast()]<nums[i])
                queue.pollLast();
            queue.offerLast(i);
        }
        int[] res=new int[nums.length-k+1];
        res[0]=nums[queue.peek()];
        int l=1;
        if (queue.peek()<1)
            queue.poll();
        int index=1;
        for (int i=k;i<nums.length;i++){
            while (!queue.isEmpty()&&nums[queue.peekLast()]<nums[i])
                queue.pollLast();
            queue.offerLast(i);
            res[index++]=nums[queue.peek()];
            if (queue.peek()<=i-k+1)
                queue.poll();
        }
        return res;
    }

    //
    public void moveZeroes2(int[] nums) {
        int index=0;
        for (int i=0;i<nums.length;i++){
            if (nums[i]!=0)
                nums[index++]=nums[i];
        }
        while (index++<nums.length)
            nums[index]=0;

    }

    //
    public int findDuplicate_(int[] nums) {
        int i=1;
        int j=1;
        i=nums[i];
        j=nums[nums[j]];
        while (nums[i]!=nums[j]){
            i=nums[i];
            j=nums[nums[j]];
        }
        i=0;
        while (nums[i]!=nums[j]){
            i=nums[i];
            j=nums[j];
        }
        return nums[i];
    }
    //zi jie
    public int lengthOfLongestSubstring5(String s) {
        HashMap<Character,Integer> index=new HashMap();
        int maxlen=Integer.MIN_VALUE;
        int curlen=0;
        for(int i=0;i<s.length();i++){
            if(index.containsKey(s.charAt(i))){
                int gap=i-index.get(s.charAt(i));
                if(gap<curlen){
                    curlen=gap;
                }else{
                    curlen++;
                    maxlen=Math.max(maxlen,curlen);
                }
                index.put(s.charAt(i),i);
            }else{
                curlen++;
                maxlen=Math.max(maxlen,curlen);
                index.put(s.charAt(i),i);
            }
        }
        return maxlen;
    }

    //300
    public int lengthOfLIS34(int[] nums) {
        if (nums.length==1)
            return 1;
        int[] ends=new int[nums.length];
        ends[0]=nums[0];
        int bound=0;
        for (int i=1;i<nums.length;i++){
            if (nums[i]==ends[bound])
                continue;
            if(nums[i]>ends[bound]){
                bound++;
                ends[bound]=nums[i];
                continue;
            }
            int l=0;
            int r=bound;
            while (l<r){
                int mid=l+(r-l)/2;
                if(ends[mid]<nums[i])
                    l=mid+1;
                else
                    r=mid;
            }
            ends[l]=nums[i];
        }
        return bound;
    }

    //198打家劫舍
    public int rob_leetcode(int[] nums) {
        if (nums.length==1)
            return nums[0];
        if (nums.length==2)
            return nums[1]>nums[0]?nums[1]:nums[0];
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        dp[1]=nums[1]>nums[0]?nums[1]:nums[0];
        for (int i=2;i<nums.length;i++){
            dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]);
        }
        return dp[nums.length-1];
    }

    //213 rob2
    public int rob222(int[] nums) {
        if (nums.length==1)
            return nums[0];
        if (nums.length==2)
            return nums[1]>nums[0]?nums[1]:nums[0];
        //steal the first one
        int[] dp1=new int[nums.length];
        dp1[0]=nums[0];
        dp1[1]=nums[0];
        for (int i=2;i<nums.length-1;i++)
            dp1[i]=Math.max(dp1[i-1],dp1[i-2]+nums[i]);
        int res=dp1[nums.length-2];
        //steal the last one
        int[] dp2=new int[nums.length];
        dp2[0]=0;
        dp2[1]=nums[1];
        for(int i=2;i<nums.length;i++)
            dp2[i]=Math.max(dp2[i-1],dp2[i-2]+nums[i]);
        res=res>dp2[nums.length-1]?res:dp2[nums.length-1];
        return res;
    }

    //120
    public int minimumTotal1(List<List<Integer>> triangle) {
        int size = triangle.size();
        if (size==1)
            return triangle.get(0).get(0);
        int len = triangle.get(size - 1).size();
        int[][] dp=new int[len][len];
        dp[0][0]=triangle.get(0).get(0);
        int minlen=Integer.MAX_VALUE;
        for (int i=1;i<triangle.size();i++){
            for (int j=0;j<=i;j++){
                if (j==0)
                    dp[i][j]=dp[i-1][j]+triangle.get(i).get(j);
                else if (j==i)
                    dp[i][j]=dp[i-1][j-1]+triangle.get(i).get(j);
                else
                    dp[i][j]=Math.min(dp[i-1][j],dp[i-1][j-1])+triangle.get(i).get(j);
                if(i==triangle.size()-1)
                    minlen=Math.min(dp[i][j],minlen);
            }
        }
        return minlen;
    }
    public int minimumTotal(List<List<Integer>> triangle) {
        int size = triangle.size();
        if (size==1)
            return triangle.get(0).get(0);
        int len = triangle.get(size - 1).size();
        int[] dp=new int[len];
        dp[0]=triangle.get(0).get(0);
        int minlen=Integer.MAX_VALUE;
        for (int i=1;i<triangle.size();i++){
            for (int j=i;j>=0;j--){
                if (j==0)
                    dp[j]=dp[j]+triangle.get(i).get(j);
                else if (j==i)
                    dp[j]=dp[j-1]+triangle.get(i).get(j);
                else
                    dp[j]=Math.min(dp[j],dp[j-1])+triangle.get(i).get(j);
                if(i==triangle.size()-1)
                    minlen=Math.min(dp[j],minlen);
            }
        }
        return minlen;
    }

    //309
    public int maxProfit_cold(int[] prices) {
        if (prices.length==1)
            return 0;
        //持有，不持有不冷冻，不持有冷冻
        int[][] dp=new int[prices.length][3];
        dp[0][0]=-prices[0];
        for (int i=1;i< prices.length;i++){
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][2]);
            dp[i][2]=dp[i-1][0]+ prices[i];
        }
        return Math.max(dp[prices.length-1][1],dp[prices.length-1][2]);
    }

    //322
    public int coinChange2(int[] coins, int amount) {
        int[] dp=new int[amount+1];
        dp[0]=0;
        Arrays.fill(dp,1,dp.length,Integer.MAX_VALUE);
        for (int i=0;i<coins.length;i++){
            for (int j=coins[i];j<amount;j++){
                if (dp[amount-j]!=Integer.MAX_VALUE)
                    dp[j]=Math.min(dp[j],dp[amount-j]+1);
            }
        }
        return dp[dp.length-1]==Integer.MAX_VALUE?-1:dp[dp.length-1];
    }

    public int minCount=Integer.MAX_VALUE;
    public int coinChange3(int[] coins, int amount) {
        Arrays.sort(coins);
        dfs4coin(coins,amount,0,coins.length-1);
        return minCount==Integer.MAX_VALUE?-1:minCount;
    }
    public void dfs4coin(int[] coins,int cur_amount,int count,int index){
        if (index<0||count+cur_amount/coins[index]>minCount)
            return;
        if (cur_amount%coins[index]==0)
            minCount=Math.min(minCount,count+cur_amount/coins[index]);
        for (int i=cur_amount/coins[index];i>=0;i--)
            dfs4coin(coins,cur_amount-i*coins[index],count+i,index-1);
    }

    public int coinChange(int[] coins, int amount) {
        int[] dp=new int[amount+1];
        int max=amount+1;
        dp[0]=0;
        Arrays.fill(dp,1,dp.length,max);
        for (int i=1;i<=amount;i++){
            for (int j=0;j<coins.length;j++){
                if (coins[j]<amount)
                    dp[i]=Math.min(dp[i],dp[i-coins[j]+1]);
            }
        }
        return dp[amount]==max?-1:dp[amount];
    }

    class robReturn{
        int maxval1;//contains the root
        int maxval2;//not contains the root

        robReturn(int maxval1,int maxval2){
            this.maxval1=maxval1;
            this.maxval2=maxval2;
        }
    }
    public int rob(TreeNode root) {
        if (root==null)
            return 0;
        robReturn robReturn = process4rob(root);
        return Math.max(robReturn.maxval1,robReturn.maxval2);
    }
    public robReturn process4rob(TreeNode root){
        if (root==null)
            return new robReturn(0,0);
        robReturn lr = process4rob(root.left);
        robReturn rr = process4rob(root.right);
        int res1=lr.maxval2+rr.maxval2+root.val;
        int res2=Math.max(lr.maxval1,lr.maxval2)+Math.max(rr.maxval1,rr.maxval2);
        return new robReturn(res1,res2);
    }

    //347
    public class data4top{
        int num;
        int freq;

        public data4top(int num,int freq){
            this.num=num;
            this.freq=freq;
        }
    }
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer,Integer> map=new HashMap<>();
        for (int i=0;i<nums.length;i++){
            if (!map.containsKey(nums[i])){
                map.put(nums[i],1);
            }else {
                map.put(nums[i],map.get(nums[i])+1);
            }
        }
        data4top[] res=new data4top[map.size()];
        int index=0;
        for (Integer i:map.keySet()){
            res[index++]=new data4top(i,map.get(i));
        }
        Arrays.sort(res, Comparator.comparingInt(o -> -o.freq));
        int[] res_=new int[k];
        for (int i=0;i<k;i++){
            res_[i]=res[i].num;
        }
        return res_;
    }

    public int[] topKFrequent2(int[] nums, int k) {
        HashMap<Integer,Integer> map=new HashMap<>();
        for (int i:nums)
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);
        //小顶堆
        PriorityQueue<int[]> priorityQueue=new PriorityQueue<int[]>((o1,o2)->{
            return o1[1]-o2[1];
        });
        for (Integer i:map.keySet()){
            Integer val = map.get(i);
            if (priorityQueue.size()==k){
                if (priorityQueue.peek()[1]<val){
                    priorityQueue.poll();
                    priorityQueue.offer(new int[]{i,val});
                }
            }else
                priorityQueue.offer(new int[]{i,val});
        }
        int[] res=new int[k];
        for (int i=0;i<res.length;i++){
            res[i]=priorityQueue.poll()[0];
        }
        return res;
    }

    //394
    public String decodeString2(String s) {
        int num_index=-1;
        for (int i=0;i<s.length();i++){
            if (Character.isDigit(s.charAt(i))){
                num_index=i;
                break;
            }
        }
        if (num_index==-1)
            return s;
        int num_index_s=num_index;
        int num=0;
        while(Character.isDigit(s.charAt(num_index))){
            num=num*10+s.charAt(num_index)-'0';
            num_index++;
        }
        num_index-=1;
        StringBuilder sb=new StringBuilder();
        String cur=s.substring(0,num_index_s);
        sb.append(cur);
        int pos=0;
        int count=0;
        for (int i=num_index+1;i<s.length();i++){
            if (s.charAt(i)=='[')
                count++;
            else if (s.charAt(i)==']'){
                count--;
                if (count==0){
                    pos=i;
                    break;
                }
            }
        }
        String extra1 = s.substring(num_index + 2, pos);
        String extra11=decodeString(extra1);
        for (int i=0;i<num;i++)
            sb.append(extra11);
        String extra2=s.substring(pos+1);
        sb.append(decodeString(extra2));
        return sb.toString();
    }

    public String decodeString(String s) {
        Stack<Integer> nums=new Stack<>();
        Stack<String>  strs=new Stack<>();
        int num=0;
        String res="";
        for (int i=0;i<s.length();i++){
            if (Character.isDigit(s.charAt(i)))
                num=num*10+s.charAt(i)-'0';
            else if ('a'<=s.charAt(i)&&s.charAt(i)<='z')
                res+=s.charAt(i);
            else if (s.charAt(i)=='['){
                nums.push(num);
                num=0;
                strs.push(res);
                res="";
            }else {
                Integer count = nums.pop();
                String tmp= strs.pop();
                for (int j=0;j<count;j++)
                    tmp+=res;
                res=tmp;
            }
        }
        return res;
    }

    public String decodeString3(String s) {
        Stack<Integer> nums=new Stack<>();
        Stack<String> strs=new Stack<>();
        int num=0;
        String str="";
        for(int i=0;i<s.length();i++){
            if (Character.isDigit(s.charAt(i))){
                num=num*10+s.charAt(i)-'0';
            }else if (s.charAt(i)>='a'&&s.charAt(i)<='z'){
                str+=s.charAt(i);
            }else if (s.charAt(i)=='['){
                nums.push(num);
                num=0;
                strs.push(str);
                str="";
            }else {
                int count=nums.pop();
                String tmp=strs.pop();
                for (int j=0;j<count;j++)
                    tmp+=str;
                str=tmp;
            }
        }
        return str;
    }

    //309 股票 包含冷冻期
    public int maxProfit5(int[] prices) {
        int[][] dp=new int[prices.length][3];
        //持有 不持有并且之后不是冷冻期 不持有并且之后是冷冻期
        dp[0][0]=-prices[0];
        dp[0][1]=0;
        dp[0][2]=0;
        for (int i=1;i< prices.length;i++){
            //持有
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
            //不持有，并且之后不是冷冻期
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][2]);
            //不持有，并且之后是冷冻期
            dp[i][2]= dp[i-1][0]+prices[i];
        }
        return Math.max(dp[prices.length-1][1],dp[prices.length-1][2]);
    }

    //448
    public List<Integer> findDisappearedNumbers(int[] nums) {
        for (int i=0;i<nums.length;i++){
            while (nums[i]!=i+1&&nums[nums[i]-1]!=nums[i]){
                swap4findDispear(nums,i,nums[i]-1);
            }
        }
        List<Integer> res=new ArrayList<>();
        for (int i=0;i<nums.length;i++){
            if (nums[i]!=i+1)
                res.add(i+1);
        }
        return res;
    }
    public void swap4findDispear(int[] nums,int x,int y){
        int tmp=nums[x];
        nums[x]=nums[y];
        nums[y]=tmp;
    }

    public List<Integer> findDisappearedNumbers2(int[] nums) {
        for(int i=0;i<nums.length;i++){
            if (nums[Math.abs(nums[i])-1]>0)
                nums[Math.abs(nums[i])-1]=-Math.abs(nums[nums[i]-1]);
        }
        List<Integer> res=new ArrayList<>();
        for (int i=0;i<nums.length;i++){
            if (nums[i]>=0)
                res.add(i+1);
        }
        return res;
    }

    //461
    public int hammingDistance(int x, int y) {
        int res_num=x^y;
        int count=0;
        while (res_num!=0){
            int tmp=res_num&1;
            if (tmp==1)
                count++;
            res_num>>=1;
        }
        return count;
    }

    //494
    public int count4ways;
    public int findTargetSumWays(int[] nums, int target) {
        process4sumWays(nums,target,0,0);
        return count4ways;
    }
    public void process4sumWays(int[] nums,int target,int index,int cur){
        if (index==nums.length-1){
            if(cur+nums[index]==target||cur-nums[index]==target){
                if (nums[index]==0)
                    count4ways+=1;
                count4ways+=1;
            }
            return;
        }
        process4sumWays(nums,target,index+1,cur+nums[index]);
        process4sumWays(nums,target,index+1,cur-nums[index]);
    }

    //399  这个题 是抄的评论，有时间再看看！！！！
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
            int count=0;
            HashMap<String,Integer> map=new HashMap<>();
            for (List<String> list:equations){
                for (String s:list){
                    if(!map.containsKey(s))
                        map.put(s,count++);
                }
            }
            double[][] graph=new double[count+1][count+1];
            for (String s:map.keySet()){
                Integer i = map.get(s);
                graph[i][i]=1.0;
            }
            int index=0;
            for (List<String> list:equations){
                String a = list.get(0);
                String b = list.get(1);
                Integer a1 = map.get(a);
                Integer b1 = map.get(b);
                graph[a1][b1]=values[index];
                graph[b1][a1]=1/values[index++];
            }
            int n=count+1;
            for (int i=0;i<n;i++){
                for (int j=0;j<n;j++){
                    for (int k=0;k<n;k++){
                        if (j==k||graph[j][k]!=0) continue;
                        if (graph[j][i]!=0&&graph[i][k]!=0){
                            graph[j][k]= graph[j][i]*graph[i][k];
                        }
                    }
                }
            }
            double[] res=new double[queries.size()];
            for (int i=0;i<res.length;i++){
                List<String> strings = queries.get(i);
                String q1 = strings.get(0);
                String q2 = strings.get(1);
                if (map.containsKey(q1)&&map.containsKey(q2)){
                    double ans=graph[map.get(q1)][map.get(q2)];
                    res[i]=ans==0?-1.0:ans;
                }else
                    res[i]=-1.0;
            }
            return res;
    }

    //438
    public List<Integer> findAnagrams2(String s, String p) {
        if (s.length()<p.length())
            return new ArrayList<>();
        int[] pcount=new int[26];
        for (int i=0;i<p.length();i++)
            pcount[p.charAt(i)-'a']++;
        int dif=p.length();
        ArrayList<Integer> res=new ArrayList<>();
        for (int i=0,j=0;i<s.length();i++){
            while (j<s.length()&&pcount[s.charAt(j)-'a']>0){
                dif--;
                pcount[s.charAt(j++)-'a']--;
            }
            if (dif==0)
                res.add(i);
            dif++;
            pcount[s.charAt(i)-'a']++;
        }
        return res;
    }

    //322
    public int coinChange4(int[] coins, int amount) {
        int[][] dp=new int[coins.length][amount+1];
        for (int i=0;i<coins.length;i++)
            dp[i][0]=0;
        int max=amount+1;
        for (int j=1;j<=amount;j++){
            if (j%coins[0]==0)
                dp[0][j]=j/coins[0];
            else
                dp[0][j]=max;
        }
        for (int i=1;i<coins.length;i++){
            for (int j=1;j<=amount;j++){
                dp[i][j]=dp[i-1][j];
                if (j-coins[i]>=0)
                    dp[i][j]=Math.min(dp[i][j],dp[i][j-coins[i]]+1);
            }
        }
        int res=max;
        for (int i=0;i<coins.length;i++){
                res=Math.min(res,dp[i][amount]);
        }
        return res==max?-1:res;
    }

    //518
    public int change(int amount, int[] coins) {
        int[][] dp=new int[coins.length][amount+1];
        for (int i=0;i<coins.length;i++)
            dp[i][0]=1;
        for (int j=0;j*coins[0]<=amount;j++)
            dp[0][j*coins[0]]=1;
        for (int i=1;i<coins.length;i++){
            for (int j=1;j<=amount;j++){
                dp[i][j]=dp[i-1][j];
                dp[i][j]+=j-coins[i]>=0?dp[i][j-coins[i]]:0;
            }
        }
        return dp[coins.length-1][amount];
    }

    //1089
    //使用了额外空间
    public void duplicateZeros2(int[] arr) {
        int[] res=new int[arr.length];
        int j=0;
        for (int i=0;i<arr.length&&j<res.length;i++){
            res[j++]=arr[i];
            if (arr[i]==0){
                if (j+1<res.length)
                    res[j++]=arr[i];
            }
        }
        for(int i=0;i<arr.length;i++)
            arr[i]=res[i];
    }

    //时间复杂度高
    public void duplicateZeros1(int[] arr) {
        for (int i=0;i<arr.length;i++){
            if (arr[i]==0){
                for (int j=arr.length-1;j>i;j--){
                    arr[j]=arr[j-1];
                }
                if (i+1<arr.length)
                    arr[i+1]=0;
                i++;
            }
        }
    }

    //1089
    public void duplicateZeros23(int[] arr) {
        int top=0;
        int i=0;
        for (;i<arr.length;i++){
            if (top>=arr.length)
                break;
            if (arr[i]!=0)
                top+=1;
            else
                top+=2;
        }
        i--;
        int j=arr.length-1;
        if (top==arr.length+1){
            arr[j]=0;
            j--;
            i--;
        }
        while (j>=0){
            if (arr[i]==0){
                arr[j]=0;
                arr[j-1]=0;
                j-=2;
                i--;
            }else {
                arr[j--]=arr[i--];
            }
        }
    }

    public void duplicateZeros(int[] arr) {
        int count=0;
        int index=0;
        for (;index<arr.length;index++){
            if (count>=arr.length)
                break;
            if (arr[index]!=0)
                count+=1;
            else
                count+=2;
        }
        index--;
        int j=arr.length-1;
        if (count==arr.length+1){
            arr[j]=0;
            j--;
            index--;
        }
        while(j>=0) {
            if (arr[index] == 0) {
                arr[j] = 0;
                arr[j - 1] = 0;
                j -= 2;
                index--;
            } else
                arr[j--] = arr[index--];
        }
    }

    //437
    int count4path;
    public int pathSum(TreeNode root, int targetSum) {
        if (root==null)
            return 0;
       findPath(root,targetSum,0);
       pathSum(root.left,targetSum);
       pathSum(root.right,targetSum);
       return count4path;
    }

    public void findPath(TreeNode node,int target,int cur){
        if (node==null)
            return ;
       if (cur+node.val==cur)
           count4path++;
       findPath(node.left,target,cur+node.val);
       findPath(node.right,target,cur+node.val);
    }

    //437 前缀和
    public int pathSum4(TreeNode root, int targetSum) {
            HashMap<Integer,Integer> data=new HashMap<>();
            data.put(0,1);
            return dfs4path(root,targetSum,0,data);
    }
    public int dfs4path(TreeNode node,int target,int cur,HashMap<Integer,Integer> data){
            if (node==null)
                return 0;
            int res=0;
            cur+=node.val;
            res+=data.getOrDefault(cur-target,0);
            data.put(cur,data.getOrDefault(cur,0)+1);
            res+=dfs4path(node.left,target,cur,data);
            res+=dfs4path(node.right,target,cur,data);
            data.put(cur,data.get(cur)-1);
            return res;
    }

    //538
    int pre4bst=0;
    public TreeNode convertBST(TreeNode root) {
        if (root==null)
            return root;
        convertBST(root.right);
        root.val=root.val+pre4bst;
        pre4bst=root.val;
        convertBST(root.left);
        return root;
    }

    //543

    class diameterType{
        int depth;
        int maxPath;

        diameterType(int depth,int maxPath){
            this.depth=depth;
            this.maxPath=maxPath;
        }
    }
    public int diameterOfBinaryTree2(TreeNode root) {
        if (root==null)
            return 0;
        return  help4diameter(root).maxPath;
    }
    public diameterType help4diameter(TreeNode node){
        if (node==null)
            return new diameterType(0,0);
        diameterType l = help4diameter(node.left);
        diameterType r= help4diameter(node.right);
        int curdepth=Math.max(l.depth,r.depth)+1;
        int curmax=Math.max(l.depth+r.depth,Math.max(l.maxPath,r.maxPath));
        return new diameterType(curdepth,curmax);
    }

    int maxDia;
    public int diameterOfBinaryTree(TreeNode root) {
                if (root==null)
                    return 0;
               depth4diameter(root);
               return maxDia;
    }
    public int depth4diameter(TreeNode node){
        if (node==null)
            return 0;
        int l=depth4diameter(node.left);
        int r=depth4diameter(node.right);
        maxDia=Math.max(maxDia,l+r);
        return Math.max(l,r)+1;
    }

    //416
    boolean flag4split=false;
    public boolean canPartition_bt(int[] nums) {
        tb4split(nums,0,0);
        return flag4split;
    }
    public void tb4split(int[] nums,int gap,int index){
        if (index==nums.length){
            if (gap==0)
                flag4split=true;
            return ;
        }
        tb4split(nums,gap-nums[index],index+1);
        tb4split(nums,gap+nums[index],index+1);
    }

    public boolean canPartition(int[] nums){
        int sum=0;
        for (int i:nums){
            sum+=i;
        }
        if (sum%2==1)
            return false;
        int target=sum/2;
        int[][] dp=new int[nums.length+1][target+1];
        for (int i=1;i<dp.length;i++){
            for (int j=1;j<dp[0].length;j++){
                if (j<nums[i-1])
                    dp[i][j]=dp[i-1][j];
                else {
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-nums[i-1]]+nums[i-1]);
                }
            }
        }
        return dp[nums.length][target]==target?true:false;
    }

    public boolean canPartition2(int[] nums){
        int sum=0;
        for (int i:nums){
            sum+=i;
        }
        if (sum%2==1)
            return false;
        int target=sum/2;
        int[] dp=new int[target+1];
        for (int i=1;i<nums.length;i++){
            for (int j=target;j>=1;j--){
                if (j<nums[i-1])
                    dp[j]=dp[j-1];
                else {
                    dp[j]=Math.max(dp[j],dp[j-nums[i-1]]+nums[i-1]);
                }
            }
        }
        return dp[target]==target?true:false;
    }

    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people,(arr1,arr2)->{
            if (arr1[0]!=arr2[0])
                return arr2[0]-arr1[0];
            else
                return arr1[1]-arr2[1];
        });
        List<int[]> res=new ArrayList<>();
        for (int[] person:people)
            res.add(person[1],person);
        return res.toArray(new int[res.size()][]);
    }

    public boolean canPartition4(int[] nums){
        int sum=0;
        for (int i=0;i<nums.length;i++)
            sum+=nums[i];
        if (sum%2==1)
            return false;
        int target=sum/2;
        int[][] dp=new int[nums.length+1][target+1];
        for (int i=1;i<dp.length;i++){
            for (int j=1;j<dp[0].length;j++){
                if (nums[i-1]>j)
                    dp[i][j]=dp[i-1][j];
                else
                    dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-nums[i-1]]+nums[i-1]);
            }
        }
        return dp[dp.length-1][target]==target;
    }

    //617
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
                if (root1==null)
                    return root2;
                if (root2==null)
                    return root1;
                TreeNode nhead=new TreeNode(root1.val+root2.val);
                nhead.left=mergeTrees(root1.left,root2.left);
                nhead.right=mergeTrees(root1.right,root2.right);
                return nhead;
    }

    //560 自己做出来了，但是还是可以优化一下，具体看下面
    public int subarraySum1(int[] nums, int k) {
            int[] sum=new int[nums.length];
            int pre_sum=0;
            for (int i=0;i<sum.length;i++){
                sum[i]=pre_sum+nums[i];
                pre_sum=sum[i];
            }
            int count=0;
            HashMap<Integer,Integer> pre_sum_count=new HashMap<>();
            pre_sum_count.put(0,1);
            for (int i=0;i<sum.length;i++){
                if (pre_sum_count.get(sum[i]-k)!=null){
                    count+=pre_sum_count.get(sum[i]-k);
                }
                pre_sum_count.put(sum[i],pre_sum_count.getOrDefault(sum[i],0)+1);
            }
            return count;

    }

    public int subarraySum(int[] nums, int k) {
        HashMap<Integer,Integer> map=new HashMap<>();
        map.put(0,1);
        int sum=0;
        int count=0;
        for (int i=0;i<nums.length;i++){
            sum+=nums[i];
            if (map.containsKey(sum-k)){
                count+=map.get(sum-k);
            }
            map.put(sum,map.getOrDefault(sum,0)+1);
        }
        return count;
    }

    //581
    //不是很懂 再好好看看！
    public int findUnsortedSubarray2(int[] nums) {
            int n=nums.length;
            int maxn=Integer.MIN_VALUE;
            int minn=Integer.MAX_VALUE;
            int right=-1;
            int left=-1;
            for (int i=0;i<n;i++){
                if (maxn>nums[i]){
                    right=i;
                }else {
                    maxn=nums[i];
                }
                if (minn<nums[n-1-i]){
                    left=n-1-i;
                }else {
                    minn=nums[n-1-i];
                }
            }
            return right==-1?0:right-left+1;
    }

    public int findUnsortedSubarray(int[] nums) {
        int len=nums.length;
        int max=Integer.MIN_VALUE;
        int min=Integer.MAX_VALUE;
        int right=-1;
        for (int i=0;i<len;i++){
            if (nums[i]>=max)
                max=nums[i];
            else
                right=i;
        }
        if (right==-1)
            return 0;
        int left=-1;
        for (int i=len-1;i>=0;i--){
            if (nums[i]<=min)
                min=nums[i];
            else
                left=i;
        }
        return right-left+1;
    }

    //739 每日温度
    public int[] dailyTemperatures2(int[] temperatures) {
            int[] res=new int[temperatures.length];
            for (int i=0;i<temperatures.length;i++){
                int count=0;
                int cur=temperatures[i];
                for (int j=i+1;j<temperatures.length;j++){
                    count++;
                    if (temperatures[j]>temperatures[i]){
                        res[i]=count;
                        break;
                    }
                }
                if (count==0)
                    res[i]=0;
            }
            return res;
    }

    public int[] dailyTemperatures22(int[] temperatures) {
        if (temperatures.length==1)
            return new int[]{0};
        int[] res=new int[temperatures.length];
        res[temperatures.length-1]=0;
        res[temperatures.length-2]=temperatures[temperatures.length-2]<temperatures[temperatures.length-1]?1:0;
        for (int i=temperatures.length-3;i>=0;i--){
            if (temperatures[i]<temperatures[i+1])
                res[i]=1;
            else {
                int span=1+res[i+1];
                if (res[i+1]==0)
                    res[i]=0;
                else{
                    while (temperatures[i+span]<temperatures[i]){
                        if (res[i+span]==0) {
                            res[i] = 0;
                            break;
                        }
                        span+=res[i+span];
                    }
                    if (temperatures[i+span]>temperatures[i])
                        res[i]=span;
                }
            }
        }
        return res;
    }

    //单调栈解法
    public int[] dailyTemperatures(int[] temperatures) {
        Deque<Integer> queue=new ArrayDeque<>();
        int[] res=new int[temperatures.length];
        for (int i=0;i<temperatures.length;i++){
            while (!queue.isEmpty()&&temperatures[queue.peek()]<temperatures[i]){
                Integer idx = queue.poll();
                res[idx]=i-idx;
            }
            queue.push(i);
        }
        return res;
    }

    //647 回文子串
    public int countSubstrings1(String s) {
            int len=s.length();
            int[][] dp=new int[len][len];
            int res=0;
            for (int j=0;j<len;j++){
                for (int i=0;i<=j;i++){
                    if (s.charAt(i)==s.charAt(j)){
                        if ((j-i<=2)||dp[i+1][j-1]==1)
                            dp[i][j]=1;
                        if (dp[i][j]==1)
                            res++;
                    }
                }
            }
            return res;
    }

    //回文子串 优化空间 （不对）
    public int countSubstrings3(String s) {
        int len=s.length();
        int[] dp=new int[len];
        int res=0;
        for (int j=0;j<len;j++){
            for (int i=j;i>=0;i--){
                if (s.charAt(i)==s.charAt(j)){
                    if ((j-i<=2)||dp[j-1]==1)
                        dp[j]=1;
                    if (dp[j]==1)
                        res++;
                }
            }
        }
        return res;
    }

    public int countSubstrings(String s) {
        //https://leetcode.cn/problems/palindromic-substrings/solution/liang-dao-hui-wen-zi-chuan-de-jie-fa-xiang-jie-zho/
        int ans=0;
        for (int i=0;i<s.length()*2-1;i++){
            int left=i/2;
            int right=left+i%2;
            while (left>=0&&right<s.length()&&s.charAt(left)==s.charAt(right)){
                left--;
                right++;
                ans++;
            }
        }
        return ans;
    }

    //621
    public int leastInterval(char[] tasks, int n) {
            int[] hash=new int[26];
            for (int i=0;i<tasks.length;i++){
                hash[tasks[i]-'A']+=1;
            }
            Arrays.sort(hash);
            int minlen=(n+1)*(hash[25]-1)+1;
            for (int i=0;i<hash.length-1;i++){
                if (hash[i]==hash[25])
                    minlen++;
            }
            return Math.max(minlen,tasks.length);
    }

    //53
    public int maxSubArray22(int[] nums) {
        if (nums.length==1)
            return nums[0];
        int max=nums[0];
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        for (int i=1;i<nums.length;i++){
            if (dp[i-1]>0){
                dp[i]=dp[i-1]+nums[i];
            }else
                dp[i]=nums[i];
            max=Math.max(max,dp[i]);
        }
        return max;
    }

    //45
    public int jump(int[] nums) {
        if (nums.length==1)
            return 0;
        //dp[i] means the minest count of the jump to the nums[i]
        int[] dp=new int[nums.length];
        dp[0]=0;
        Arrays.fill(dp,1,dp.length,Integer.MAX_VALUE);
        for (int i=0;i<nums.length;i++){
            int count=nums[i];
            for (int j=1;j<=count;j++){
                if (i+j<nums.length){
                    dp[i+j]=Math.min(dp[i+j],dp[i]+1);
                }
            }
        }
        return dp[nums.length-1];
    }

    public int jump2(int[] nums) {
        if (nums.length==1)
            return 0;
        int step=0;
        int cur_pos=0;
        while (cur_pos<nums.length-1){
            int count=nums[cur_pos];
            int move=1;
            for (int i=1;i<=count;i++){
                if (cur_pos+i>=nums.length-1)
                    return ++step;
                if (nums[cur_pos+move]+move<nums[cur_pos+i]+i) move=i;
            }
            cur_pos+=move;
            step++;
        }
        return step;
    }

    //55    跳跃游戏1
    public boolean canJump2(int[] nums) {
        if (nums.length==1)
            return true;
        Boolean[] res=new Boolean[nums.length];
        res[0]=true;
        for (int i=1;i<res.length;i++){
            for (int j=0;j<i;j++){
                if (res[j]==true&&j+nums[j]>=i){
                    res[i]=true;
                    break;
                }
            }
        }
        return res[nums.length-1];
    }

    public boolean canJump(int[] nums) {
        if (nums.length==1)
            return true;
        int maxBound=0;
        boolean canJump=false;
        for (int i=0;i<nums.length&&i<=maxBound;i++){
            maxBound=Math.max(maxBound,i+nums[i]);
            if (i+nums[i]>=nums.length-1){
                canJump=true;
                break;
            }
        }
        return canJump;

    }

    // jianzhi 095
    public int longestCommonSubsequence(String text1, String text2) {
        char[] chars1 = text1.toCharArray();
        char[] chars2 = text2.toCharArray();
        int[][] dp=new int[chars1.length][chars2.length];
        //base case
        dp[0][0]=text1.charAt(0)==text2.charAt(0)?1:0;
        for (int i=1;i<text1.length();i++)
            dp[i][0]=Math.max(dp[i-1][0],text1.charAt(i)==text2.charAt(0)?1:0);
        for (int j=1;j<text2.length();j++)
            dp[0][j]=Math.max(dp[0][j-1],text1.charAt(0)==text2.charAt(j)?1:0);
        //dp
        for (int i=1;i<text1.length();i++){
            for (int j=1;j<text2.length();j++){
                dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                if (text1.charAt(i)==text2.charAt(j))
                    dp[i][j]=Math.max(dp[i][j],dp[i-1][j-1]+1);
            }
        }
        return dp[dp.length-1][dp[0].length-1];
    }

    //最长公共子串
    //可以优化空间，变成只用几个变量的形式
    //具体看下面解答
    public void longestCommonSubString(String string1,String string2){
        char[] s1 = string1.toCharArray();
        char[] s2 = string2.toCharArray();
        int[][] dp=new int[s1.length][s2.length];
        //base
        for (int i=0;i<s1.length;i++){
            if (s1[i]==s2[0])
                dp[i][0]=1;
        }
        for (int j=0;j<s2.length;j++){
            if (s1[0]==s2[j])
                dp[0][j]=1;
        }
        for (int i=1;i<s1.length;i++){
            for (int j=1;j<s2.length;j++){
                if (s1[i]==s2[j])
                    dp[i][j]=dp[i-1][j-1]+1;
            }
        }
        int end=0;
        int max=0;
        for (int i=0;i<s1.length;i++){
            for (int j=0;j<s2.length;j++){
                if (dp[i][j]>max){
                    max=dp[i][j];
                    end=i;
                }
            }
        }
        System.out.println(string1.subSequence(end-max+1,end+1));
        System.out.println(max);
    }

    //这是上一个题，节省空间的解法（从m*n的空间，到只用常数级别空间）
    //照着写的，感觉不难，但感觉实际自己写的时候，有一些坑，需要再好好看看！！！
    public void longestCommonSubString2(String str1,String str2){
        char[] s1 = str1.toCharArray();
        char[] s2 = str2.toCharArray();
        int row=0;
        int col=s2.length-1;
        int max=0;
        int end=0;
        while (row<s1.length){
            int i=row;
            int j=col;
            int len=0;
            while (i<s1.length&&j<s2.length){
                if (s1[i]==s2[j]){
                    len++;
                }else
                    len=0;
                if (len>max){
                    max=len;
                    end=i;
                }
                i++;
                j++;
            }
            if (col>0)
                col--;
            else
                row++;
        }
        System.out.println(str1.substring(end-max+1,end+1));
        System.out.println(max);
    }

    //406
    public int[][] reconstructQueue3(int[][] people) {
        Arrays.sort(people,(p1,p2)->{
            if(p1[0]!=p2[0])
                return p2[0]-p1[0];
            else
                return p1[1]-p2[1];
        });
        ArrayList<int[]> res=new ArrayList<>();
        for (int[] arr:people)
            res.add(arr[1],arr);
        return res.toArray(new int[res.size()][]);
    }

    //416
    public boolean canPartition222(int[] nums){
        int sum=0;
        for (int i:nums)
            sum+=i;
        if (sum%2==1)
            return false;
        int halfSum=sum/2;
        int[][] dp=new int[nums.length][halfSum+1];
        for (int i=0;i<nums.length;i++)
            dp[i][0]=0;
        for (int j=1;j<halfSum+1;j++){
            if (j>=nums[0])
                dp[0][j]=nums[0];
        }
        for (int i=1;i<nums.length;i++){
            for (int j=1;j<halfSum+1;j++){
                if (j>nums[i])
                    dp[i][j]=dp[i-1][j-nums[i]]+nums[i];
                dp[i][j]=Math.max(dp[i][j],dp[i-1][j]);
            }
        }
        return dp[nums.length-1][halfSum]==halfSum?true:false;
    }


    public int nextGreaterElement(int n) {
        char[] chars = Integer.toString(n).toCharArray();
        int start=-1;
        for (int i=chars.length-1;i>0;i--){
            if (chars[i-1]-'0'<chars[i]-'0'){
                start=i-1;
            }
        }
        if (start==-1)
            return -1;
        reverse4generate(chars,start+1);
        for (int i=start+1;i<chars.length;i++){
            if (chars[i]-'0'>chars[start]-'0'){
                char tmp=chars[start];
                chars[start]=chars[i];
                chars[i]=tmp;
                break;
            }
        }
        long l = Long.parseLong(new String(chars));
        return l>Integer.MAX_VALUE?-1:(int)l;
    }
    public void reverse4generate(char[] chars,int begin){
        int start=begin;
        int end=chars.length-1;
        while (start<end){
            char tmp=chars[start];
            chars[start]=chars[end];
            chars[end]=tmp;
            start++;
            end--;
        }
    }

    //最长回文子序列
    public int longestPalindromeSubseq(String s) {
        if (s.length()==0||s.equals(""))
            return 0;
        int[][] dp=new int[s.length()][s.length()];
        for (int i=0;i<s.length();i++)
            dp[i][i]=1;
        for (int i=0;i<s.length()-1;i++)
            dp[i][i+1]=s.charAt(i)==s.charAt(i+1)?2:1;
        for (int i=s.length()-2;i>=0;i--){
            for (int j=i+1;j<s.length();j++){
                dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                if (s.charAt(i)==s.charAt(j))
                    dp[i][j]=Math.max(dp[i][j],dp[i-1][j-1]+2);
            }
        }
        return dp[0][s.length()-1];
    }

    //最长回文子串
    public String longestPalindrome2(String s) {
        if (s.length()<2||s.equals("")||s==null)
            return s;
        //dp presents if the substring s[i__j] is the palindrome
        //1 = true 0=false
        int[][] dp=new int[s.length()][s.length()];
        for (int i=0;i<s.length();i++)
            dp[i][i]=1;
        int maxlen=1;
        int start=0;
        for(int j=1;j<s.length();j++){
            for (int i=0;i<j;i++){
                if (s.charAt(i)==s.charAt(j)){
                    if (j-i<3)
                        dp[i][j]=1;
                    else {
                        dp[i][j]=dp[i+1][j-1];
                    }
                }
                if (dp[i][j]==1&&j-i+1>maxlen){
                    maxlen=j-i+1;
                    start=i;
                }
            }
        }
        return s.substring(start,start+maxlen);
    }

    //648

    class TireNode{
        char val;
        TireNode[] children;
        int pass;
        int end;

        TireNode(char val){
            this.val=val;
            children=new TireNode[26];
        }
    }
    class Tire{
        TireNode root;
        Tire(){
            this.root=new TireNode('+');
        }

        public void add(String s){
            TireNode cur=root;
            for (int i=0;i<s.length();i++){
                if (cur.children[s.charAt(i)-'a']!=null){
                    cur=cur.children[s.charAt(i)-'a'];
                    cur.pass++;
                }else {
                    cur.children[s.charAt(i)-'a']=new TireNode(s.charAt(i));
                    cur=cur.children[s.charAt(i)-'a'];
                    cur.pass++;
                }
            }
            cur.end++;
        }

        public String findRoot(String s){
            TireNode cur=root;
            StringBuilder sb=new StringBuilder();
            for (int i=0;i<s.length();i++){
                if (cur.end>0)
                    return sb.toString();
                if (cur.children[s.charAt(i)-'a']==null){
                    return s;
                }else {
                    sb.append(s.charAt(i));
                    cur=cur.children[s.charAt(i)-'a'];
                }
            }
            return s;
        }
    }
    public String replaceWords(List<String> dictionary, String sentence) {
        Tire root=new Tire();
        for (String s:dictionary){
            root.add(s);
        }
        String[] words = sentence.split(" ");
        for (int i=0;i< words.length;i++){
            words[i]=root.findRoot(words[i]);
        }
        return String.join(" ",words);
    }


    //518
    public int change333(int amount, int[] coins) {
        int[][] dp=new int[coins.length][amount+1];
        for (int i=0;i<coins.length;i++)
            dp[i][0]=1;
        for (int j=0;j<=amount;j++)
            dp[0][j]=j%coins[0]==0?1:0;
        for (int i=1;i<coins.length;i++){
            for (int j=1;j<=amount;j++){
                dp[i][j]=dp[i-1][j];
                if (j>=coins[i])
                    dp[i][j]+=dp[i][j-coins[i]];
            }
        }
        return dp[coins.length-1][amount];
    }


    //剑指offer19
    public boolean isMatch(String s, String p) {
        char[] sc = s.toCharArray();
        char[] pc = p.toCharArray();
        return process4match(sc,pc,0,0);
    }
    public boolean process4match(char[] c1,char[] c2,int s1,int s2){
        if (s2==c2.length)
            return s1==c1.length;
        //c2[s2+1]!=*
        if (s2+1==c2.length||c2[s2+1]!='*')
            return s1!=c1.length&&
                    (c1[s1]==c2[s2]||c2[s2]=='.')&&process4match(c1,c2,s1+1,s2+1);
        //c2[s2+1]==*
        while (s1!=c1.length&&(c1[s1]==c2[s2]||c2[s2]=='.')){
            if (process4match(c1,c2,s1,s2+2))
                return true;
            s1+=1;
        }
        return process4match(c1,c2,s1,s2+2);
    }

    //剑指008
    public int minSubArrayLen(int target, int[] nums) {
        if (nums.length==0)
            return 0;
        int i=0;
        int j=0;
        int sum=0;
        int min=Integer.MAX_VALUE;
        while (j<nums.length){
            sum+=nums[j];
            while (sum>=target){
                min=Math.min(min,j-i+1);
                sum-=nums[i];
                i++;
            }
            j++;
        }
        return min==Integer.MAX_VALUE?0:min;
    }

    //剑指067
    class xorNode{
        xorNode[] nexts=new xorNode[2];
    }
    xorNode root=new xorNode();
    public void insetXOR(int num){
        xorNode p=root;
        for (int i=30;i>=0;i--){
            int tmp=(num>>i)&1;
            if (tmp==0){
                if (p.nexts[0]==null)
                    p.nexts[0]=new xorNode();
                p=p.nexts[0];
            }else {
                if (p.nexts[1]==null)
                    p.nexts[1]=new xorNode();
                p=p.nexts[1];
            }
        }
    }
    public int findMaxXOR(int num){
            xorNode p=root;
            int ans=0;
            for (int i=30;i>=0;i--){
                int tmp=(num>>i)&1;
                tmp=p.nexts[tmp^1]==null?tmp:tmp^1;
                ans+=(tmp<<i);
                p=p.nexts[tmp];
            }
            return ans;
    }
    public int findMaximumXOR(int[] nums) {
        int max=Integer.MIN_VALUE;
        for (int num:nums){
            insetXOR(num);
            int tmp_max = findMaxXOR(num);
            max=Integer.max(max,tmp_max);
        }
        return max;

    }

    //21
    public ListNode mergeTwoLists2(ListNode list1, ListNode list2) {
            if (list1==null)
                return list2;
            if (list2==null)
                return list1;
            if (list1.val<list2.val){
                list1.next=mergeTwoLists2(list1.next,list2);
                return list1;
            }else {
                list2.next=mergeTwoLists2(list1,list2.next);
                return list2;
            }
    }


    //offer 41

    /*int size4queue=0;
    Queue<Integer> queue4average=new LinkedList<>();
    double sum=0;
    int cur_count=0;
    public MovingAverage(int size) {
        size4queue=size;
    }

    public double next(int val) {
        if (cur_count==size4queue){
            Integer out = queue4average.poll();
            sum-=out;
            sum+=val;
            queue4average.offer(val);
            return sum/size4queue;
        }else {
            sum+=val;
            cur_count++;
            queue4average.offer(val);
            return sum/cur_count;
        }
    }*/

    //565

    //时间复杂度太高了
    int max4mesting=Integer.MIN_VALUE;
    public int arrayNesting2(int[] nums) {
        int len=nums.length;
        for (int i=0;i<len;i++)
            process4meeting(i,new HashSet<>(),nums);
        return max4mesting;
    }
    public void process4meeting(int i,HashSet<Integer> set,int[] nums){
        while (true){
            int tmp=nums[i];
            if (!set.contains(tmp)) {
                set.add(tmp);
                i=tmp;
            }else
                break;
        }
        max4mesting=Math.max(max4mesting,set.size());
    }


    public int arrayNesting(int[] nums) {
        //flag that shows that one node has been visited
        int flag=nums.length;
        int ans=0;
        for (int i=0;i<nums.length;i++){
            int len=0;
            int tmp=i;
            while (nums[tmp]!=flag){
                len+=1;
                int orginal=tmp;
                tmp=nums[tmp];
                nums[orginal]=flag;
            }
            ans=Math.max(len,ans);
        }
        return ans;
    }

    //134加油站
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int[] gap=new int[gas.length];
        for (int i=0;i< gas.length;i++)
            gap[i]=gas[i]-cost[i];
        int i=0;
        while (i<gas.length){
                if (gap[i]<0){
                    i++;
                    continue;
                }else {
                    int curOil=gap[i];
                    int curPos=nextPos(i,gap.length);
                    int cnt=0;
                    while (cnt<gas.length&&curOil>=0){
                        curOil+=gap[curPos];
                        curPos=nextPos(curPos, gas.length);
                        cnt+=1;
                    }
                    if (cnt==gas.length)
                        return i;
                    else
                        i=i+cnt+1;
                }
        }
        return -1;
    }
    public int nextPos(int index,int len){
        if (index==len-1)
            return 0;
        else
            return index+1;
    }

    //8
    public int myAtoi(String s) {
        char[] chars = s.toCharArray();
        int idx=0;
        while (idx<chars.length&&chars[idx]==' '){
            idx++;
        }
        if (idx==chars.length)
            return 0;
        int flag=1;
        int res=0;
        if (chars[idx]=='-'){
            flag=-1;
        }else if (chars[idx]=='+'){
            flag=1;
        }else if (Character.isDigit(chars[idx])){
            res=chars[idx]-'0';
        }else
            return 0;
        idx++;
        while (idx<chars.length&&Character.isDigit(chars[idx])){
            int dight=chars[idx]-'0';
            if (res>(Integer.MAX_VALUE-dight)/10)
                return flag==1?Integer.MAX_VALUE:Integer.MIN_VALUE;
            res=res*10+dight;
        }
        return flag==1?res:-res;
    }

    //10
    public boolean isMatch22(String s, String p) {
            return process4match(s,p,0,0);
    }
    public boolean process4match(String s,String p,int idx1,int idx2){
        if (idx2==p.length())
            return idx1==s.length();
        //after element is not *
        if (idx2==p.length()-1||p.charAt(idx2+1)!='*')
            return idx1<s.length()&&(p.charAt(idx2)=='.'||p.charAt(idx2)==s.charAt(idx1))
                    &&process4match(s,p,idx1+1,idx2+1);
        //after element is *
        while (idx1<s.length()&&(s.charAt(idx1)==p.charAt(idx2)||p.charAt(idx2)=='.')){
            if (process4match(s,p,idx1,idx2+2))
                return true;
            idx1+=1;
        }
        return process4match(s,p,idx1,idx2+2);
    }

    //36
    public boolean isValidSudoku(char[][] board) {
        int[][] row=new int[9][9];
        int[][] col=new int[9][9];
        int[][][] blocks=new int[3][3][9];
        for (int i=0;i< board.length;i++){
            for (int j=0;j<board[0].length;j++){
                if (board[i][j]!='.'){
                    int dight=board[i][j]-'0';
                    int idx=dight-1;
                    row[i][idx]++;
                    col[j][idx]++;
                    blocks[i/3][j/3][idx]++;
                    if (row[i][idx]>1||col[j][idx]>1||blocks[i/3][j/3][idx]>1)
                        return false;
                }
            }
        }
        return true;
    }

    //3
    public int lengthOfLongestSubstring555(String s) {
        HashMap<Character,Integer> data=new HashMap<>();
        int maxlen=Integer.MIN_VALUE;
        char[] chars = s.toCharArray();
        int curlen=0;
        for (int i=0;i<s.length();i++){
            if (!data.containsKey(chars[i])){
                curlen++;
                data.put(chars[i],i);
            }else {
                Integer preidx = data.get(chars[i]);
                if (i-preidx>curlen){
                    curlen++;
                }else
                    curlen=i-preidx;
            }
            data.put(chars[i],i);
            maxlen=Math.max(curlen,maxlen);
        }
        return maxlen;
    }

    //11
    public int maxArea22(int[] height) {
        int maxArea=0;
        int left=0;
        int right= height.length-1;
        while (left<right){
            int h=Math.min(height[left],height[right]);
            maxArea=Math.max(maxArea,h*(right-left));
            if (h== height[left])
                left++;
            else
                right--;
        }
        return maxArea;
    }

    //20 44 67
    public boolean isNumber(String s) {
        char[] chars = s.toCharArray();
        int idx=0;
        while (idx<chars.length&&chars[idx]==' ')
            idx++;
        if (idx==chars.length)
            return false;
        int last=chars.length-1;
        while (last>=0&&chars[last]==' ')
            last--;
        int flag=0;
        if (chars[idx]=='+')
            flag=1;
        else if (chars[idx]=='-')
            flag=-1;
        else if (!(Character.isDigit(chars[idx])||chars[idx]=='.'))
            return false;
        if (chars[idx]=='.'){
            idx++;
            while (Character.isDigit(chars[idx]))
                idx++;
            if (idx==last+1)
                return true;
            else if (chars[idx]=='e'||chars[idx]=='E'){
                idx++;
                if (idx>last)
                    return false;
                while (idx<=last){
                    if (!Character.isDigit(chars[idx]))
                        return false;
                    idx++;
                }
                return true;
            }else
                return false;
        }else {
            while (Character.isDigit(chars[idx]))
                idx++;
            if (idx==last+1)
                return true;
            if (chars[idx]=='.'){
                idx++;
                while (Character.isDigit(chars[idx]))
                    idx++;
                if (idx==last+1)
                    return true;
                else if (chars[idx]=='e'||chars[idx]=='E'){
                    idx++;
                    if (idx>last)
                        return false;
                    while (idx<=last){
                        if (!Character.isDigit(chars[idx]))
                            return false;
                        idx++;
                    }
                    return true;
                }else
                    return false;
            }else if (chars[idx]=='e'||chars[idx]=='E'){
                idx++;
                if (idx>last)
                    return false;
                while (idx<=last){
                    if (!Character.isDigit(chars[idx]))
                        return false;
                    idx++;
                }
                return true;
            }else
                return false;
        }
    }

    //键值offer44
    public int findNthDigit33(int n) {
        //位数
        int base=1;
        //每位的起始
        int start=1;
        //总计数量
        int count=9;
        while (count<n){
            n-=count;
            base+=1;
            start*=10;
            count*=start;
        }
        int num=(int)Math.ceil(n/base)-1;
        String s = String.valueOf(num);
        return s.charAt((n-1)%base)-'0';
    }

    //29
    /*
    给定两个整数，被除数 dividend 和除数 divisor。将两数相除，要求不使用乘法、除法和 mod 运算符。

    返回被除数 dividend 除以除数 divisor 得到的商。

    整数除法的结果应当截去（truncate）其小数部分，例如：truncate(8.345) = 8 以及 truncate(-2.7335) = -2
     */
    public int divide(int dividend, int divisor) {
        if(dividend==Integer.MIN_VALUE&&divisor==-1)
            return Integer.MAX_VALUE;
        boolean negative=(dividend^divisor)<0?true:false;
        dividend=dividend>0?-dividend:dividend;
        divisor=divisor>0?-divisor:divisor;
        int res=helper_divide(dividend,divisor);
        return negative?-res:res;
    }
    public int helper_divide(int dividend,int divisor){
            if (dividend>divisor)
                return 0;
            int count=1;
            int tmp=divisor;
            while ((tmp+tmp<0)&&(tmp+tmp>=dividend)){
                    count+=count;
                    tmp+=tmp;
            }
            return count+helper_divide(dividend-tmp,divisor);
    }

    //44
    public boolean isMatch44(String s, String p) {
        if (s==" "&&p==" ")
            return true;
        if (s==" "&&p!=" ")
            return false;
        if(s!=" "&&p==" ")
            return false;
        return helper_match(s,p,0,0);
    }
    public boolean helper_match(String s,String p,int si,int pi){
        if (pi==p.length())
            return si==s.length();
        if (p.charAt(pi)!='*'){
            if (si<s.length()&&(s.charAt(si)==p.charAt(pi)||p.charAt(pi)=='?'))
                return helper_match(s,p,si+1,pi+1);
            else
                return false;
        }else {
            for (int tmp=si;tmp<=s.length();tmp++){
                if (helper_match(s,p,tmp,pi+1))
                    return true;
            }
        }
        return false;
    }

    // 44 to dp
    public boolean isMatch44_dp(String s, String p) {
        if (s==" "&&p==" ")
            return true;
        if (s==" "&&p!=" ")
            return false;
        if(s!=" "&&p==" ")
            return false;
        boolean[][] dp=new boolean[s.length()+1][p.length()+1];
        dp[s.length()][p.length()]=true;
        for (int j=p.length()-1;j>=0;j--){
            for (int i=0;i<=s.length();i++){
                if (p.charAt(j)!='*'){
                    if (i<s.length()&&(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?'))
                        dp[i][j]=dp[i+1][j+1];
                    else
                        dp[i][j]=false;
                }else {
                    for (int tmp=i;tmp<=s.length();tmp++){
                        if (dp[tmp][j+1]==true)
                            dp[i][j]=true;
                    }
                }
            }
        }
        return dp[0][0];
    }

    //50
    public double myPow(double x, int n) {
        if (n==0)
            return 1.0;
        if (n==1)
            return x;
        if (n==-1)
            return 1/x;
        double tmp;
        if (n%2==0){
            tmp=myPow(x,n/2);
            return tmp*tmp;
        }else {
            tmp=myPow(x,n/2);
            if (n>0)
                return tmp*tmp*x;
            else
                return tmp*tmp*(1/x);
        }
    }

    //91
    int totalcount_91=0;
    public int numDecodings(String s) {
        process4_91(s,0);
        return totalcount_91;
    }
    public void process4_91(String s,int index){
        if (index>=s.length()){
            totalcount_91++;
            return;
        }
        if (s.charAt(index)-'0'==0)
            return;
        if (index==s.length()-1)
            process4_91(s,index+1);
        else {
            int num1 =s.charAt(index)-'0';
            int num2=s.charAt(index+1)-'0';
            int num=num1*10+num2;
            if (1<=num&&num<=26){
                if (num2==0){
                    process4_91(s, index + 2);
                }else {
                    process4_91(s, index + 1);
                    process4_91(s, index + 2);
                }
            }else {
                if (num2==0){
                    totalcount_91=0;
                    return;
                }
                process4_91(s, index + 1);
            }
        }
    }

    //91 to dp
    public int numDecodings_dp(String s) {
        int[] dp=new int[s.length()];
        dp[s.length()-1]=s.charAt(s.length()-1)-'0'==0?0:1;
        if (s.length()==1)
            return dp[0];
        int n1=s.charAt(s.length()-2)-'0';
        int n2=s.charAt(s.length()-1)-'0';
        if (n1==0)
            dp[s.length()-2]=0;
        else {
            int totoal = n1 * 10 + n2;
            if (1 <= totoal && totoal <= 26){
                if (n2==0){
                    dp[s.length()-2]=1;
                }else {
                    dp[s.length()-2]=2;
                }
            }
            else{
                if(n2==0)
                    return 0;
                dp[s.length() - 2] = 1;
            }
        }

        for (int index=dp.length-3;index>=0;index--){
            int num1 =s.charAt(index)-'0';
            int num2=s.charAt(index+1)-'0';
            if (num1==0){
                dp[index]=0;
                continue;
            }
            int num=num1*10+num2;
            if (1<=num&&num<=26){
                if (num2==0){
                    dp[index]=dp[index+2];
                }else {
                    dp[index]=dp[index+1]+dp[index+2];
                }
            }else {
                if (num2 == 0) {
                    return 0;
                }
                dp[index]=dp[index+1];
            }
        }
        return dp[0];
    }

    public int numDecodings2(String s) {
        if (s.length()==1)
            return s.charAt(0)-'0'==0?0:1;
        int[] dp=new int[s.length()+1];
        dp[s.length()]=0;
        dp[s.length()-1]=s.charAt(s.length()-1)-'0'==0?0:1;
        for (int index=s.length()-2;index>=0;index--){
            int num1 =s.charAt(index)-'0';
            int num2=s.charAt(index+1)-'0';
            if (num1==0){
                dp[index]=0;
                continue;
            }
            int num=num1*10+num2;
            if (1<=num&&num<=26){
                if (num2==0){
                    dp[index]=dp[index+2];
                }else {
                    dp[index]=dp[index+1]+dp[index+2];
                }
            }else {
                if (num2 == 0) {
                    return 0;
                }
                dp[index]=dp[index+1];
            }
        }
        return dp[0];
    }

    //84
    //暴力解法

    //超时
    public int largestRectangleArea(int[] heights) {
        int maxArea=0;
        for (int i=0;i< heights.length;i++){
            int height=heights[i];
            int len=1;
            int tmp=i-1;
            while (tmp>=0&&heights[tmp]>=heights[i]){
                len++;
                tmp--;
            }
            tmp=i+1;
            while (tmp<heights.length&&heights[tmp]>=heights[i]){
                len++;
                tmp++;
            }
            maxArea=Math.max(maxArea,len*height);
        }
        return maxArea;
    }

    //通过单调栈进行优化
    public int largestRectangleArea_2(int[] heights) {
        int maxArea=0;
        Stack<Integer> stack=new Stack<>();
        int[] tmp_arr=new int[heights.length+2];
        tmp_arr[0]=tmp_arr[tmp_arr.length-1]=0;
        for (int i=1;i<tmp_arr.length-1;i++)
            tmp_arr[i]= heights[i-1];
        for (int i=0;i< tmp_arr.length;i++){
            while (!stack.isEmpty()&&tmp_arr[i]<tmp_arr[stack.peek()]){
                int height=tmp_arr[stack.pop()];
                maxArea=Math.max(maxArea,(i-stack.peek()-1)*height);
            }
            stack.push(i);
        }
        return maxArea;
    }

    //76
    public String minWindow2222(String s, String t) {
        HashMap<Character,Integer> map=new HashMap<>();
        for (int i=0;i<t.length();i++)
            map.put(t.charAt(i),map.getOrDefault(t.charAt(i),0)+1);
        int left=0;
        int right=0;
        int diff=t.length();
        int minlen=Integer.MAX_VALUE;
        int start=-1;
        while (right<s.length()){
            map.put(s.charAt(right),map.getOrDefault(s.charAt(right),0)-1);
            if (map.get(s.charAt(right))>=0)
                diff--;
            if (diff==0){
                while (map.get(s.charAt(left))<0){
                    map.put(s.charAt(left),map.get(s.charAt(left))+1);
                    left++;
                }
                minlen=Math.min(minlen,right-left+1);
                if (minlen==right-left+1)
                    start=left;
                diff++;
                map.put(s.charAt(left),map.get(s.charAt(left))+1);
                left++;
            }
            right++;
        }
        return start==-1?"":s.substring(start,start+minlen);
    }

    //5
    public String longestPalindrome6666(String s) {
        if (s=="")
            return s;
        int[][] dp=new int[s.length()][s.length()];
        for (int i=0;i<s.length();i++)
            dp[i][i]=1;
        int maxlen=0;
        int start=-1;
        for (int j=1;j<s.length();j++){
            for (int i=0;i<j;i++){
                if (s.charAt(i)==s.charAt(j)){
                    if (j-i<3)
                        dp[i][j]=1;
                    else
                        dp[i][j]=dp[i+1][j-1];
                }
                if (dp[i][j]==1&&j-i+1>maxlen){
                    maxlen=j-i+1;
                    start=i;
                }
            }
        }
        return s.substring(start,start+maxlen);
    }

    //10
    public boolean isMatch7777(String s, String p) {
        return process5match777(s,p,0,0);
    }
    public boolean process5match777(String s,String p,int i,int j){
        if (j==p.length())
            return i==s.length();
        //next element of p is not *
        if (j==p.length()-1||p.charAt(j+1)!='*')
            return i<s.length()&&(s.charAt(i)==p.charAt(j)||p.charAt(j)=='.')
                    &&process5match777(s,p,i+1,j+1);
        //next element of p is *
        while (i<s.length()&&(s.charAt(i)==p.charAt(j)||p.charAt(j)=='*')){
            if (process5match777(s,p,i,j+2))
                return true;
            i+=1;
        }
        return process5match777(s,p,i,j+2);
    }

    //4
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m=nums1.length;
        int n=nums2.length;
        int pos1=(m+n+1)/2;
        int pos2=(m+n+2)/2;
        return (findKnumOfTwoArrays(nums1,nums2,0,0,pos1)+findKnumOfTwoArrays(nums1,nums2,0,0,pos2))>>1;

    }
    //i ,j represents the start of the array nums1,nums2
    public int findKnumOfTwoArrays(int[] nums1,int[] nums2 ,int i,int j,int k){
        if (i>nums1.length)
            return nums2[j+k-1];
        if (j>nums2.length)
            return nums1[i+k-1];
        if (k==1)
            return nums1[i]>nums2[j]?nums2[j]:nums1[i];
        int midv1=(i+k/2-1)>nums1.length?Integer.MAX_VALUE:nums1[i+k/2-1];
        int midv2=(j+k/2-1)>nums2.length?Integer.MAX_VALUE:nums2[j+k/2-1];
        if (midv1>midv2){
            return findKnumOfTwoArrays(nums1,nums2,i,j+k/2,k-k/2);
        }else
            return findKnumOfTwoArrays(nums1,nums2,i+k/2,j,k-k/2);
    }

    //19
    public ListNode removeNthFromEnd555(ListNode head, int n) {
        ListNode fast=head;
        int tmp=n;
        while (tmp-->0)
            fast=fast.next;
        ListNode res=head;
        ListNode pre=head;
        while (fast!=null&&fast.next!=null){
            fast=fast.next;
            pre=pre.next;
        }
        if (fast==null)
            return res.next;
        pre.next=pre.next.next;
        return res;
    }

    //103
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> res=new ArrayList<>();
        if (root==null)
            return res;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        int left2right=1;
        while (!queue.isEmpty()){
            int size=queue.size();
            LinkedList<Integer> tmp=new LinkedList<>();
            while (size-->0){
                TreeNode poll = queue.poll();
                if (poll.left!=null)
                    queue.offer(poll.left);
                if (poll.right!=null)
                    queue.offer(poll.right);
                if (left2right==1)
                    tmp.offerFirst(poll.val);
                else
                    tmp.offerFirst(poll.val);
            }
            res.add(tmp);
            left2right^=1;
            System.out.println(left2right);
        }
        return res;
    }

    //108
    //将有序数组转换成平衡（左右高度相差最多1）的二叉搜索树
    public TreeNode sortedArrayToBST(int[] nums) {
            return process4toBST(nums,0,nums.length-1);
    }
    public TreeNode process4toBST(int[] nums,int left,int right){
        if (left>right)
            return null;
        if (left==right)
            return new TreeNode(nums[left]);
        int mid=(right+left)>>1;
        TreeNode root=new TreeNode(nums[mid]);
        root.left=process4toBST(nums,left,mid-1);
        root.right=process4toBST(nums,mid+1,right);
        return root;
    }

    //116
    //具体看leetcode

    //118
    //ez题目
    public List<List<Integer>> generate(int numRows) {
            List<List<Integer>> res=new LinkedList<>();
            LinkedList<Integer> pre=null;
            for (int i=1;i<=numRows;i++){
                LinkedList<Integer> tmp=new LinkedList<>();
                if (pre==null){
                    tmp.add(1);
                }else {
                    for (int j=0;j<i;j++){
                        if (j==0||j==i-1)
                            tmp.add(1);
                        else
                            tmp.add(pre.get(j)+pre.get(j-1));
                    }
                }
                res.add(tmp);
                pre=tmp;
            }
            return res;
    }

    //122
    /*
    给你一个整数数组 prices ，其中 prices[i] 表示某支股票第 i 天的价格。

在每一天，你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买，然后在 同一天 出售。

返回 你能获得的 最大 利润 。
     */
    public int maxProfit122(int[] prices) {
            //dp[i][0] represents the profit that the i th don't own the share
            int[][] dp=new int[prices.length][2];
            dp[0][0]=0;
            dp[0][1]=-prices[0];
            for (int i=1;i<dp.length;i++){
                dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]);
                dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
            }
            return Math.max(0,dp[dp.length-1][0]);
    }

    //125
    //ez
    public boolean isPalindrome(String s) {
        String s1 = s.toUpperCase();
        if (s1=="")
            return true;
        int left=0;
        int right=s.length()-1;
        while (left<right){
            while (left<s1.length()&&!(Character.isDigit(s1.charAt(left))||Character.isLetter(s1.charAt(left))))
                left++;
            while (right>=0&&!(Character.isDigit(s1.charAt(right))||Character.isLetter(s1.charAt(right))))
                right--;
            if (left>=s1.length()||right<0)
                return true;
            if (s1.charAt(left)!=s1.charAt(right))
                return false;
            left++;
            right--;
        }
        return true;
    }

    //131
    List<List<String>> res4pattion;
    boolean[][] dp;
    public List<List<String>> partition(String s) {
        //使用dp判断一个范围内的字符串是否是回文串
        dp=new boolean[s.length()][s.length()];
        for (int i=0;i<s.length();i++)
            dp[i][i]=true;
        for (int j=1;j<s.length();j++){
            for (int i=0;i<j;i++) {
                if (i+1==j)
                    dp[i][j]=s.charAt(i)==s.charAt(j);
                else
                    dp[i][j] = dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
            }
        }
        res4pattion=new LinkedList<>();
        process4ppartiton(s,0,new LinkedList<>());
        return res4pattion;
    }
    public void process4ppartiton(String s,int index,LinkedList<String> tmp){
        if (index>=s.length()){
            //这里需要注意，添加的是和当前tmp中元素相同的新链表，而不是tmp
            //因为tmp是递归过程中一直在用的，一直在变得，所以需要新的链表保存tmp的状态
            res4pattion.add(new ArrayList<>(tmp));
            return;
        }
        for (int i=index;i<s.length();i++){
            if (dp[index][i]){
                tmp.add(s.substring(index,i+1));
                process4ppartiton(s,i+1,tmp);
                //这里需要注意，要移除上面递归中添加的新元素
                tmp.remove(tmp.size()-1);
            }
        }
    }

    /*public boolean dis4pat(String s,int start,int end){
        while (start<end){
            if (s.charAt(start)!=s.charAt(end))
                return false;
            start++;
            end--;
        }
        return true;
    }*/



    //130
    /*
    给你一个 m x n 的矩阵 board ，由若干字符 'X' 和 'O' ，找到所有被 'X' 围绕的区域，并将这些区域里所有的 'O' 用 'X' 填充。
     */
    public void solve130(char[][] board) {
        //处理左右边界上的o
        for (int i=0;i<board.length;i++){
            if (board[i][0]=='O')
                process4solveox(board,i,0);
            if (board[i][board[0].length-1]=='O')
                process4solveox(board,i,board[0].length-1);
        }
        //处理上下边界上的o
        for (int j=1;j<board[0].length-1;j++){
            if (board[0][j]=='O'){
                process4solveox(board,0,j);
            }
            if (board[board.length-1][j]=='O'){
                process4solveox(board,board.length-1,j);
            }
        }
        for (int i=0;i<board.length;i++){
            for (int j=0;j<board[0].length;j++){
                if (board[i][j]=='O')
                    board[i][j]='X';
                if (board[i][j]=='A')
                    board[i][j]='O';
            }
        }
    }
    public void process4solveox(char[][] board,int x,int y){
        if (x<0||x>=board.length||y<0||y>=board[0].length||board[x][y]!='O')
            return;
        board[x][y]='A';
        process4solveox(board,x+1,y);
        process4solveox(board,x-1,y);
        process4solveox(board,x,y+1);
        process4solveox(board,x,y-1);
    }

    //127
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        boolean[] visited=new boolean[wordList.size()];
        Queue<String> queue=new LinkedList<>();
        queue.offer(beginWord);
        int count=0;
        while (!queue.isEmpty()){
            int size = queue.size();
            while (size-->0){
                String poll = queue.poll();
                for (int i=0;i< visited.length;i++){
                    if (!visited[i]){
                        if (diff4ladder(poll,wordList.get(i))){
                            if (wordList.get(i).equals(endWord))
                                return count+1;
                            queue.offer(wordList.get(i));
                            visited[i]=true;
                        }
                    }
                }
            }
            count++;
        }
        return 0;
    }
    public boolean diff4ladder(String s1,String s2){
        int count=0;
        for (int i=0;i<s1.length();i++){
            if (s1.charAt(i)!=s2.charAt(i))
                count++;
        }
        return count==1;
    }

    //300 最长递增子序列
    public int lengthOfLIS300(int[] nums) {
        int[] dp=new int[nums.length];
        dp[0]=1;
        int[] ends=new int[nums.length];
        ends[0]=nums[0];
        int maxlen=1;
        int right=0;
        for (int i=1;i<nums.length;i++){
            if (nums[i]>ends[right]) {
                ends[++right] = nums[i];
                dp[i]=right+1;
            }else {
                int l=0;
                int r=right;
                while (l<=r){
                    int mid=(l+r)/2;
                    if (ends[mid]<nums[i]){
                        l=mid+1;
                    }else {
                        r=mid-1;
                    }
                }
                ends[l]=nums[i];
                dp[i]=l+1;
            }
            maxlen=Math.max(maxlen,dp[i]);
        }
        return maxlen;
    }

    //354
    public int maxEnvelopes(int[][] envelopes) {
        //宽度按从小到大排列，如果宽度相同，高度按照从大到小排列
        Arrays.sort(envelopes,(a1,a2)->{
            if (a1[0]==a2[0])
                return a2[1]-a1[1];
            else
                return a1[0]-a2[0];
        });
        int[] tmp=new int[envelopes.length];
        for (int i=0;i<tmp.length;i++)
            tmp[i]=envelopes[i][1];
        return lis4maxEvelopes(tmp);
    }
    //这个函数就是300题的lis，数组的最长递增子序列
    public int lis4maxEvelopes(int[] arr){
        int[] dp=new int[arr.length];
        int[] ends=new int[arr.length];
        dp[0]=1;
        ends[0]=arr[0];
        int end=0;
        int maxlen=1;
        for (int i=1;i<arr.length;i++){
            if (arr[i]>ends[end]){
                ends[++end]=arr[i];
                dp[i]=end+1;
            }else {
               //二分
               int l=0;
               int r=end;
               while (l<=r){
                   int mid=(l+r)/2;
                   if (ends[mid]<arr[i]){
                       l=mid+1;
                   }else {
                       r=mid-1;
                   }
               }
               ends[l]=arr[i];
               dp[i]=l+1;
            }
            maxlen=Math.max(maxlen,dp[i]);
        }
        return  maxlen;
    }

    //23
    //使用小顶堆
    public ListNode mergeKLists23_1(ListNode[] lists) {
        PriorityQueue<ListNode> priorityQueue=new PriorityQueue<>((node1,node2)->{
            return node1.val-node2.val;
        });
        ListNode tmp;
        ListNode pre;
        for (ListNode head:lists){
            tmp=head;
            while (tmp!=null){
                priorityQueue.offer(tmp);
                pre=tmp;
                tmp=tmp.next;
                //这里要注意，每次往小顶堆中添加一个节点的时候，要把它的next指针断开，否则后面连接了之后，会出现cycle
                pre.next=null;
            }
        }
        ListNode res=new ListNode(0);
        ListNode ptr=res;
        while (priorityQueue.size()!=0){
            ptr.next=priorityQueue.poll();
            ptr=ptr.next;
        }
        return res.next;
    }

    //使用分治
    public ListNode mergeKLists23_2(ListNode[] lists) {
        return merge4_23(lists,0,lists.length-1);
    }
    public ListNode merge4_23(ListNode[] lists,int l,int r){
        if (l==r)
            return lists[l];
        if (l>r)
            return null;
        int mid=(l+r)/2;
        return mergeTwoList4_23(merge4_23(lists,l,mid),merge4_23(lists,mid+1,r));
    }
    public ListNode mergeTwoList4_23(ListNode l1,ListNode l2){
        ListNode dummy=new ListNode(-1);
        ListNode ptr=dummy;
        while (l1!=null&&l2!=null){
            if (l1.val<l2.val){
                ptr.next=l1;
                l1=l1.next;
                ptr=ptr.next;
            }else{
                ptr.next=l2;
                l2=l2.next;
                ptr=ptr.next;
            }
        }
        while (l1!=null){
            ptr.next=l1;
            l1=l1.next;
            ptr=ptr.next;
        }
        while (l2!=null){
            ptr.next=l2;
            l2=l2.next;
            ptr=ptr.next;
        }
        return dummy.next;
    }


    //25
    public ListNode reverseKGroup25(ListNode head, int k) {
            ListNode dummy=new ListNode(-1);
            dummy.next=head;
            ListNode pre=dummy;
            ListNode end=dummy;
            while (end.next!=null){
                for (int i=0;i<k&&end!=null;i++)
                    end=end.next;
                if (end==null)
                    break;
                ListNode next_list_head=end.next;
                ListNode reversed_tail=pre.next;
                end.next=null;
                pre.next=reverseList(pre.next);
                reversed_tail.next=next_list_head;
                pre=reversed_tail;
                end=reversed_tail;
            }
            return dummy.next;
    }

    public ListNode reverseList(ListNode node){
        ListNode pre=null;
        ListNode cur=node;
        while (cur!=null){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

    //26
    public int removeDuplicates(int[] nums) {
        int index=0;
        for (int i=0;i<nums.length;i++){
            if (i==0||nums[i]!=nums[i-1])
                nums[index++]=nums[i];
        }
        return index+1;
    }


    public static int printArr(int[] arr){
        for (int i:arr)
            System.out.print(i+" ");
        return -1;
    }

    //27
    public int removeElement(int[] nums, int val) {
        int index=0;
        for (int i=0;i<nums.length;i++){
            if (nums[i]!=val)
                nums[index++]=nums[i];
        }
        return index+1;
    }

    //29
    //题解第二个，递归的思想
    public int divide29(int dividend, int divisor) {
        //particular case
        if (dividend==Integer.MIN_VALUE&&divisor==-1)
            return Integer.MAX_VALUE;
        boolean negative=(dividend^divisor)<0?true:false;
        dividend=dividend>0?-dividend:dividend;
        divisor=divisor>0?-divisor:divisor;
        int res=divide_help(dividend,divisor);
        return negative?-res:res;
    }
    public int divide_help(int dividend,int divisor){
        //默认在这个函数中，除数，和被除数，都是负数
        if (dividend>divisor)
            return 0;
        int count=1;
        int tmp=divisor;
        while ((tmp+tmp)<0&&tmp+tmp>dividend){
            count+=count;
            tmp+=tmp;
        }
        return count+divide_help(dividend-tmp,divisor);
    }


    //33
    public int search33(int[] nums, int target) {
        int n=nums.length;
        int left=0;
        int right=n-1;
        while (left<=right){
            int mid=(left+right)/2;
            if (nums[mid]==target)
                return mid;
            if (nums[mid]<nums[right]){
                if (nums[mid]<target&&target<=nums[right])
                    left=mid+1;
                else
                    right=mid-1;
            }else {
                if (nums[mid]>target&&target>=nums[left]){
                    right=mid-1;
                }else
                    left=mid+1;
            }
        }
        return -1;
    }

    //39
    public List<List<Integer>> res4_39;
    public List<List<Integer>> combinationSum39(int[] candidates, int target) {
        Arrays.sort(candidates);
        res4_39=new ArrayList<>();
        process4_39(candidates,0,0,new ArrayList<>(),target);
        return res4_39;
    }
    public void process4_39(int[] arr,int index,int curSum,List<Integer> path,int target){
        if (curSum==target){
            res4_39.add(new ArrayList<>(path));
            return;
        }
        for (int i=index;i<arr.length;i++){
            curSum+=arr[index];
            if (curSum>target)
                break;
            path.add(arr[i]);
            process4_39(arr,i,curSum,path,target);
            path.remove(path.size()-1);
        }
    }

    //45跳跃游戏
    //dp
    public int jump_dp(int[] nums) {
        int[] dp=new int[nums.length];
        dp[0]=0;
        Arrays.fill(dp,1,dp.length,Integer.MAX_VALUE);
        for (int i=0;i<nums.length;i++){
            for (int j=0;j<i;j++){
                if (nums[j]+j>=i){
                    dp[i]=Math.min(dp[i],dp[j]+1);
                }
            }
        }
        return dp[dp.length-1];
    }

    //贪心
    public int jump_tx(int[] nums) {
        if (nums.length==1)
            return 0;
        int step=0;
        int curPos=0;
        while (curPos<nums.length){
            int nextPos=curPos+1;
            int count=nums[curPos];
            if (curPos+count>=nums.length-1)
                return step+1;
            for (int i=1;i<=count;i++){
                if (nums[nextPos]+nextPos<nums[curPos+i]+curPos+i)
                    nextPos=curPos+i;
            }
            curPos=nextPos;
            step++;
        }
        return step;
    }

    //53
    public int maxSubArray53(int[] nums) {
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        int max=Integer.MIN_VALUE;
        for (int i=1;i<nums.length;i++){
            dp[i]=Math.max(nums[i],dp[i-1]+nums[i]);
            max=Math.max(dp[i],max);
        }
        return max;
    }

    //55
    public boolean canJump55(int[] nums) {
        if (nums.length==1)
            return true;
        int maxBound=0;
        boolean canJump=false;
        for (int i=0;i<nums.length&&i<=maxBound;i++){
            maxBound=Math.max(maxBound,nums[i]+i);
            if (maxBound>=nums.length-1){
                canJump=true;
                break;
            }
        }
        return canJump;
    }


    //56
    public int[][] merge56(int[][] intervals) {
        PriorityQueue<interval> priorityQueue=new PriorityQueue<>((i1,i2)->{
            if (i1.start==i2.start)
                return i1.end-i2.end;
            else
                return i1.start-i2.start;
        });
        for (int i=0;i<intervals.length;i++){
            priorityQueue.offer(new interval(intervals[i][0],intervals[i][1]));
        }
        ArrayList<interval> list=new ArrayList<>();
        while (!priorityQueue.isEmpty()){
            interval poll = priorityQueue.poll();
            while (!priorityQueue.isEmpty()&&poll.end>priorityQueue.peek().start){
                interval poll1 = priorityQueue.poll();
                poll.end=Math.max(poll.end,poll1.end);
            }
            list.add(poll);
        }
        int[][] res=new int[list.size()][2];
        for (int i=0;i<res.length;i++){
            res[i][1]=list.get(i).end;
            res[i][0]=list.get(i).start;
        }
        return res;
    }

    //61
    public ListNode rotateRight(ListNode head, int k) {
        if (head==null)
            return head;
        ListNode ptr=head;
        int len=0;
        while (ptr!=null){
            len++;
            ptr=ptr.next;
        }
        int rk=k%len;
        if (rk==0)
            return head;
        ListNode slow=head;
        ListNode fast=head;
        for (int i=0;i<k;i++)
            fast=fast.next;
        while (fast.next!=null){
            slow=slow.next;
            fast=fast.next;
        }
        fast.next=head;
        ListNode res=slow.next;
        slow.next=null;
        return res;
    }

    //138
    class tmp{
        class Node {
            int val;
            Node next;
            Node random;

            public Node(int val) {
                this.val = val;
                this.next = null;
                this.random = null;
            }
        }

        //138
        public Node copyRandomList(Node head) {
            if (head==null)
                return head;
            Node ptr=head;
            //在每一个节点后面新增一个和它值相同的节点
            while (ptr!=null){
                Node next=ptr.next;
                ptr.next=new Node(ptr.val);
                ptr.next.next=next;
                ptr=next;
            }
            Node ptr2=head;
            //复制random节点
            while (ptr2!=null){
                ptr2.next.random=ptr2.random==null?null:ptr2.random.next;
                ptr2=ptr2.next.next;
            }
            //把random链表和原链表分离
            Node ptr3=head;
            Node newN=head.next;
            while (ptr!=null&&ptr3.next!=null){
                Node tmp=ptr.next;
                ptr.next=ptr.next.next;
                ptr=tmp;
            }
            return newN;
        }
    }

    //140 单词拆分2
    public List<String> res4_140;
    public List<String> wordBreak140(String s, List<String> wordDict) {
        res4_140=new ArrayList<>();
        HashSet<String> set=new HashSet<>();
        for (int i=0;i<wordDict.size();i++)
            set.add(wordDict.get(i));
        dfs4_140(s,0,set,new ArrayList<>());
        return res4_140;
    }
    public void dfs4_140(String s, int index, HashSet<String> set, ArrayList<String> path){
        if (index==s.length()){
            res4_140.add(new String(String.join(" ",path)));
            return;
        }
        for (int i=index;i<s.length();i++){
            String substring = s.substring(index, i);
            if (set.contains(substring)){
                path.add(substring);
                dfs4_140(s,i,set,path);
                path.remove(path.size()-1);
            }
        }
    }

    //139 单词拆分1
    public boolean wordBreak139(String s, List<String> wordDict) {
        HashSet<String> set=new HashSet<>();
        for (String ss:wordDict)
            set.add(ss);
        //dp[i]代表s【0..i】是否可以被正确划分
        int[] dp=new int[s.length()+1];
        dp[0]=1;
        for (int i=1;i<dp.length;i++){
            for (int j=0;j<i;j++){
                if (dp[j]==1&&set.contains(s.substring(j+1,i+1))){
                    dp[i]=1;
                }
            }
        }
        return dp[dp.length-1]==1;
    }

    //217  so ez
    public boolean containsDuplicate(int[] nums) {
        HashSet<Integer> set=new HashSet<>();
            for (int i:num)
                set.add(i);
            return set.size()==nums.length;
    }

    //162
    public int findPeakElement162(int[] nums) {
        if (nums.length==1)
            return 0;
        if (nums[0]>nums[1])
            return 0;
        if (nums[nums.length-2]<nums[nums.length-1])
            return nums.length-1;
        int left=0;
        int right=nums.length-1;
        while (left<=right){
            int mid=(left+right)/2;
            if (nums[mid]>nums[mid-1]&&nums[mid]>nums[mid+1])
                return mid;
            if (nums[mid]>nums[mid-1])
                left=mid+1;
            else if (nums[mid]<=nums[mid-1])
                right=mid;
        }
        return -1;

    }

    //149
    public int maxPoints(int[][] points) {
        int n=points.length;
        int res=1;
        for (int i=0;i<points.length;i++){
            Map<String,Integer> map=new HashMap<>();
            int x1=points[i][0];
            int y1=points[i][1];
            int max=0;
            for (int j=i+1;j<points.length;j++){
                int x2=points[j][0];
                int y2=points[j][1];
                int z=gcd(x1-x2,y1-y2);
                int a=x1-x2;
                int b=y1-y2;
                String key=(a/z)+"_"+(b/z);
                map.put(key,map.getOrDefault(key,0)+1);
                max=Math.max(max,map.get(key));
            }
            res=Math.max(res,max+1);
        }
        return res;
    }

    public int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }

    //32
    public int longestValidParentheses322(String s) {
        if (s==" ")
            return 0;
        char[] chars = s.toCharArray();
        int[] dp=new int[s.length()];
        dp[0]=0;
        int maxlen=Integer.MIN_VALUE;
        for (int i=1;i<s.length();i++){
            if (chars[i]=='(')
                dp[i]=0;
            else {
                int lastlen=dp[i-1];
                int match_pos=i-lastlen-1;
                if (match_pos<0||chars[match_pos]!='(')
                    dp[i]=0;
                else {
                    dp[i]+=(2+dp[i-1]);
                    if (match_pos>0)
                        dp[i]+=dp[match_pos-1];
                }
            }
            maxlen=Math.max(maxlen,dp[i]);
        }
        return maxlen;
    }


    //70
    public int climbStairs(int n) {
        if (n==1)
            return 1;
        int[] dp=new int[n];
        dp[0]=1;
        dp[1]=2;
        for (int i=2;i<dp.length;i++)
            dp[i]=dp[i-1]+dp[i-2];
        return dp[dp.length-1];
    }

    //73
    public void setZeroes(int[][] matrix) {
        //先判断 首行/首列 是否有0出现
        boolean col0=false;
        boolean row0=false;
        for (int i=0;i< matrix.length;i++){
            if (matrix[i][0]==0)
                col0=true;
        }
        for (int j=0;j<matrix[0].length;j++){
            if (matrix[0][j]==0)
                row0=true;
        }

        //通过首行/首列 记录该列/行是否需要被置0
        for (int i=0;i<matrix.length;i++){
            for (int j=0;j< matrix[0].length;j++){
                if (matrix[i][j]==0){
                    matrix[i][0]=0;
                    matrix[0][j]=0;
                }
            }
        }
        for (int i=1;i<matrix.length;i++){
            for (int j=1;j<matrix[0].length;j++){
                if (matrix[i][0]==0||matrix[0][j]==0)
                    matrix[i][j]=0;
            }
        }

        if (col0){
            for (int i=0;i< matrix.length;i++){
                matrix[i][0]=0;
            }
        }

        if (row0){
            for (int i=0;i< matrix[0].length;i++){
                matrix[0][i]=0;
            }
        }


    }

    //75
    public void sortColors75(int[] nums) {
        // 0 1 2
        if (nums.length<=1)
            return;
        int lbound=-1;
        int rbound=nums.length;
        int i=0;
        while (i<rbound){
            if (nums[i]==0){
                lbound++;
                swap4_75(nums,i,lbound);
            }else if (nums[i]==2){
                rbound--;
                swap4_75(nums,i,rbound);
            }else {
                i++;
            }
        }
    }
    public void swap4_75(int[] nums,int x,int y){
        int tmp=nums[x];
        nums[x]=nums[y];
        nums[y]=tmp;
    }


    //79
    public boolean exist4_79=false;
    public boolean exist79(char[][] board, String word) {
        for (int i=0;i<board.length;i++){
            for (int j=0;j< board[0].length;j++){
                if (board[i][j]==word.charAt(0)) {
                    boolean[][] visited = new boolean[board.length][board[0].length];
                    process4_79(word, 0, visited,board,i,j);
                    if (exist4_79 == true)
                        break;
                }
            }
        }
        return exist4_79;
    }
    public void process4_79(String word,int index,boolean[][] visited,char[][] board,int x,int y){
        if (index==word.length()){
            exist4_79=true;
            return;
        }
        if (x<0||x>= visited.length||y<0||y>=visited[0].length)
            return;
        if (board[x][y]==word.charAt(index)&&visited[x][y]==false){
            visited[x][y]=true;
            process4_79(word,index+1,visited,board,x,y+1);
            process4_79(word,index+1,visited,board,x,y-1);
            process4_79(word,index+1,visited,board,x+1,y);
            process4_79(word,index+1,visited,board,x-1,y);
            visited[x][y]=false;
        }
    }

    //80
    public int removeDuplicates80(int[] nums) {
        if (nums.length<=2)
            return nums.length;
        int len=0;
        int tmp_count=0;
        int i=0;
        while (i<nums.length){
            while (i>0&&i<nums.length&&nums[i]==nums[len-1]&&tmp_count==2){
                i++;
            }
            if (i==nums.length)
                return len;
            nums[len++]=nums[i++];
            if (len>1&&nums[len-1]==nums[len-2]){
                tmp_count++;
            }else
                tmp_count=1;
        }
        return len;
    }

    //82

    //递归
    /*public ListNode deleteDuplicates(ListNode head) {
        if (head==null||head.next==null)
                return head;
        if (head.next.val==head.val){
            ListNode ptr=head.next;
            while (ptr!=null&&ptr.val==head.val){
                ptr=ptr.next;
            }
            return deleteDuplicates(ptr);
        }else{
            ListNode listNode = deleteDuplicates(head.next);
            head.next=listNode;
            return head;
        }
    }*/

    //88
    public void merge88(int[] nums1, int m, int[] nums2, int n) {
        int mm=m-1;
        int nn=n-1;
        int k=m+n-1;
        while (k>=0){
            if (mm<0||(nn>=0&&nums1[mm]<nums2[nn])){
                nums1[k--]=nums2[nn--];
            }else
                nums1[k--]=nums1[mm--];
        }
    }


    public long calculateTotal (int count) {
        // write code here
        if (count==1)
            return 1;
        if (count==2)
            return 1;
        long[] num=new long[count];
        num[0]=1;
        num[1]=1;
        for (int i=2;i<num.length;i++)
            num[i]=num[i-1]+num[i-2];
        return num[count-1];
    }

    //92
    public ListNode reverseBetween92(ListNode head, int left, int right) {
            ListNode dummmy=new ListNode(-1);
            dummmy.next=head;
            ListNode pre=dummmy;
            for (int i=0;i<left;i++)
                pre=pre.next;
            ListNode ptr=pre.next;
            for (int i=0;i<right-left;i++){
                ListNode next=ptr.next;
                ptr.next=next.next;
                pre.next=next;
                next.next=ptr;
            }
            return dummmy.next;

    }

    //96
    public int numTrees96(int n) {
        int[] num=new int[n+1];
        num[0]=1;
        num[1]=1;
        for (int i=2;i<num.length;i++){
            for (int j=1;j<=i;j++)
                num[i]+=num[j-1]*num[i-j];
        }
        return num[n];
    }

    //101
    public boolean isSymmetric101(TreeNode root) {
        return process4_101(root.left,root.right);
    }

    public boolean process4_101(TreeNode node1,TreeNode node2){
        if (node1==null&&node2==null)
            return true;
        if (node1!=null&&node2==null)
            return false;
        if (node1==null&&node2!=null)
            return false;
        if (node1.val!=node2.val)
            return false;
        return process4_101(node1.left,node2.right)&&process4_101(node1.right,node2.left);
    }

    //114
    public void flatten114(TreeNode root) {
        while (root!=null){
            if (root.left==null)
                root=root.right;
            else {
                TreeNode right_pre=root.left;
                while (right_pre.right!=null)
                    right_pre=right_pre.right;
                right_pre.right=root.right;
                root.right=root.left;
                root.left=null;
            }
        }
    }

    class tmp111 {

        public  TreeNode pre;
        public void flatten(TreeNode root) {
            //https://leetcode.cn/problems/flatten-binary-tree-to-linked-list/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--26/
            if (root==null)
                return;
            flatten(root.right);
            flatten(root.left);
            if (pre==null)
                pre=root;
            else {
                root.right=pre;
                root.left=null;
                pre=root;
            }
        }

        class Node {
            public int val;
            public Node left;
            public Node right;
            public Node next;

            public Node() {}

            public Node(int _val) {
                val = _val;
            }

            public Node(int _val, Node _left, Node _right, Node _next) {
                val = _val;
                left = _left;
                right = _right;
                next = _next;
            }
        };

    }

    //120
    public int minimumTotal120(List<List<Integer>> triangle) {
            if (triangle==null||triangle.size()==0)
                return 0;
            int[] dp=new int[triangle.get(triangle.size()-1).size()];
            for (int i=triangle.size()-1;i>=0;i++){
                List<Integer> cur_num = triangle.get(i);
                for (int j=0;j<cur_num.size();j++)
                    dp[j]=Math.min(dp[j],dp[j+1])+cur_num.get(j);
            }
            return dp[0];
    }

    //124
    public static int max4_124=Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        if (root==null)
            return 0;
        process4_124(root);
        return max4_124;
    }

    public int process4_124(TreeNode node){
        if (node==null)
            return 0;
        int i = process4_124(node.left);
        int j = process4_124(node.right);
        int curval=node.val;
        if (i>=0&&j>=0){
            max4_124=Math.max(max4_124,curval+i+j);
            return Math.max(i,j)+curval;
        }else if (i>=0&&j<0){
            max4_124=Math.max(max4_124,curval+i);
            return curval+i;
        }else if (i<0&&j>=0){
            max4_124=Math.max(max4_124,curval+j);
            return curval+j;
        }else{
            max4_124=Math.max(max4_124,curval);
            return curval;
        }
    }


    //
    /*public ListNode reverseBetween445(ListNode head, int left, int right) {
        ListNode dummmy=new ListNode(1);
        dummmy.next=head;
        ListNode pre=dummmy;
        for (int i=0;i<left;i++)
            pre=pre.next;
        ListNode ptr=pre.next;
        for (int i=0;i<right-left;i++){
            ListNode next=ptr.next;
            ptr.next=next.next;
            pre.next=next;
            next.next=ptr;
        }
        return dummmy.next;
    }*/


    /*public Node prenode=null;
    public Node res444=null;
    public Node  Convert(Node pRootOfTree) {
        process444(pRootOfTree);
        return res444;
    }


    public void process444(Node pRootOfTree){
        if (pRootOfTree==null)
            return ;
        process444(pRootOfTree.left);
        if (prenode==null){
            prenode=pRootOfTree;
            res444=pRootOfTree;
        }else {
            prenode.right=pRootOfTree;
            pRootOfTree.left=prenode;
            prenode=pRootOfTree;
        }
        process444(pRootOfTree.right);
    }*/

    public int minDistance (String a, String b) {
        // write code here
        int[][] dp=new int[a.length()+1][b.length()+1];
        for (int i=0;i<dp.length;i++)
            dp[i][0]=i;
        for (int j=0;j<dp[0].length;j++)
            dp[0][j]=j;
        for (int i=1;i<dp.length;i++){
            for (int j=1;j<dp[0].length;j++){
                if (a.charAt(i-1)==b.charAt(j-1))
                    dp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i-1][j]+1,dp[i][j-1]+1));
                else
                    dp[i][j]=Math.min(dp[i-1][j-1]+1,Math.min(dp[i-1][j]+1,dp[i][j-1]+1));
            }
        }
        return dp[a.length()][b.length()];
    }




    //
    //好久没刷算法了。。

    class temp2{
        /*
        public Node connect(Node root) {
                if (root==null)
                    return null;
                Node p1=root.left;
                Node p2=root.right;
                while (p1!=null){
                    p1.next=p2;
                    p1=p1.right;
                    p2=p2==null?null:p2.left;
                }
                connect(root.left);
                connect(root.right);
                return root;
        }

         */


        public int maxPath=Integer.MIN_VALUE;
        public int maxPathSum(TreeNode root) {
                if (root==null)
                    return 0;
                process(root);
                return maxPath;
        }

        public  int process(TreeNode root){
            if (root==null)
                return 0;
            int l=process(root.left);
            int r=process(root.right);
            if (l>=0&&r>=0){
                maxPath=Math.max(l+r+root.val,maxPath);
                return Math.max(l,r)+root.val;
            }
            if (l>=0&&r<=0){
                maxPath=Math.max(l+root.val,maxPath);
                return l+root.val;
            }
            if (l<=0&&r>=0){
                maxPath=Math.max(r+root.val,maxPath);
                return r+root.val;
            }
            maxPath=Math.max(root.val,maxPath);
            return root.val;
        }
    }


    /******/


    //两个dfs的题
    //单词接龙
    public int ladderLength22(String beginWord, String endWord, List<String> wordList) {
        Queue<String> queue=new LinkedList<>();
        HashSet<String> visited=new HashSet<>();
        queue.offer(beginWord);
        int count=0;
        while (!queue.isEmpty()){
            int size = queue.size();
            while (size>0){
                String poll = queue.poll();
                for (int i=0;i<wordList.size();i++){
                    if (!visited.contains(wordList.get(i))){
                        if (canChange(poll,wordList.get(i))){
                            if (wordList.get(i).equals(endWord))
                                return count+1;
                            visited.add(wordList.get(i));
                            queue.offer(wordList.get(i));
                        }
                    }
                }
                size--;
            }
            count++;
        }
        return 0;
    }

    public boolean canChange(String s1,String s2){
        if (s1.length()!=s2.length())
            return false;
        int distiguish=0;
        for (int i=0;i<s1.length();i++){
            if (s1.charAt(i)!=s2.charAt(i))
                distiguish++;
            if (distiguish>=2)
                return false;
        }
        return distiguish==1;
    }


    //基因序列
    public int minMutation22(String start, String end, String[] bank) {
            HashSet<String> visited=new HashSet<>();
            Queue<String> queue=new LinkedList<>();
            queue.add(start);
            int count=0;
            while (!queue.isEmpty()){
                int size = queue.size();
                while (size>0){
                    String poll = queue.poll();
                    for (int i=0;i< bank.length;i++){
                        if (!visited.contains(bank[i])){
                            if (canChange(poll,bank[i])){
                                if (bank[i].equals(end))
                                    return count+1;
                                visited.add(bank[i]);
                                queue.offer(bank[i]);
                            }
                        }
                    }
                    size--;
                }
                count++;
            }
            return -1;
    }

    public int longestConsecutive222(int[] nums) {
        HashSet<Integer> set=new HashSet<>();
        for (int i:nums)
            set.add(i);
        int res=0;
        for (int i=0;i<nums.length;i++){
            if (set.contains(nums[i]-1))
                continue;
            else {
                int count=0;
                int tmp=nums[i];
                while (set.contains(tmp)){
                    tmp++;
                    count++;
                }
                res=Math.max(count,res);
            }
        }
        return res;
    }

    public void solve4444(char[][] board) {
        for (int i=0;i< board.length;i++){
            process4xo(board,i,0);
            process4xo(board,i, board[0].length-1);
        }
        for (int j=0;j<board[0].length;j++){
            process4xo(board,0,j);
            process4xo(board,board.length-1,j);
        }

        for (int i=0;i<board.length;i++){
            for (int j=0;j<board[0].length;j++){
                if (board[i][j]=='Z')
                    board[i][j]='O';
                else
                    board[i][j]='X';
            }
        }
        return;
    }


    //x y坐标应该处于边界，并且是o
    public void process4xo(char[][] board,int x,int y){
        if (x<0||y<0||x> board.length-1||y>board[0].length-1)
            return;
        if (board[x][y]!='O')
            return;
        board[x][y]='Z';
        process4xo(board,x+1,y);
        process4xo(board,x-1,y);
        process4xo(board,x,y+1);
        process4xo(board,x,y-1);
    }


    public int reverseBits(int n) {
        int res=0;
        for (int i=0;i<32;i++){
            int lastbit=n&1;
            res=((res<<1)|lastbit);
            n>>>=1;
        }
        return res;
    }


    public int majorityElement22(int[] nums) {
        int res=nums[0];
        int count=1;
        for (int i=1;i<nums.length;i++){
            if (nums[i]!=res){
                count--;
                if (count==0){
                    res=nums[i];
                    count++;
                }
            }else
                count++;
        }
        return res;
    }

    //179
    public String largestNumber(int[] nums) {

        //注意：Arrays.sort()仅支持对引用数据类型进行自定义排序。如果是基本数据类型（如int），将无法使用Comparator进行自定义排序
        /*Arrays.sort(nums,(n1,n2)->{
            char[] c1 = String.valueOf(n1).toCharArray();
            char[] c2 = String.valueOf(n2).toCharArray();
            int minlen=Math.min(c1.length,c2.length);
            for (int i=0;i<minlen;i++){
                if (c1[i]-'0'>c2[i]-'0')
                    return  1;
                else
                    return -1;
            }
            char[] tmp=minlen==c1.length?c2:c1;
            if (tmp.length==c1.length){
                return c1[c2.length]-'0'-(c2[0]-'0');
            }else {
                return c1[0]-'0'-(c2[c1.length]-'0');
            }
        });*/
        String[] ss=new String[nums.length];
        for (int i=0;i<nums.length;i++){
            ss[i]=String.valueOf(nums[i]);
        }
        Arrays.sort(ss,(s1,s2)->{
            return -(s1+s2).compareTo(s2+s1);
        });
        StringBuffer sb=new StringBuffer();
        for (int i=0;i<ss.length;i++)
            sb.append(ss[i]);
        String s=sb.toString();
        int k=0;
        while (k<sb.length()&&s.charAt(k)=='0')
            k++;

        return s.substring(k);
    }


    //167
    //ez
    public int[] twoSum167(int[] numbers, int target) {
        int left=0;
        int right=numbers.length-1;
        while (left<right){
            int sum=numbers[left]+numbers[right];
            if (sum<target)
                left++;
            if (sum>target)
                right--;
            if (sum==target)
                return new int[]{numbers[left],numbers[right]};
        }
        return null;
    }



    //今天面了小米二面，做的二叉树的层序便利，希望能过，加油！

    public int[] missingTwo(int[] nums) {
        int n=nums.length+2;
        int assume=(n+1)*n/2;
        int sum=0;
        for (int i:nums)
            sum+=i;
        int gap=assume-sum;
        int t=gap/2;
        int haftassume=(1+t)*t/2;
        for (int i:nums){
            if (i<=t)
                haftassume-=i;
        }
        return new int[]{haftassume,assume-haftassume};
    }


    public int singleNumber44(int[] nums) {
        int res=0;
        for (int i:nums)
            res^=i;
        return res;
    }

    public boolean wordBreak44(String s, List<String> wordDict) {
            HashSet<String> set=new HashSet<>();
            for (String ss:wordDict)
                set.add(ss);
            return process(s,0,set);
    }

    public boolean process(String s,int index,HashSet<String> set){
            if (index>=s.length())
                return true;
            for (int i=index+1;i<=s.length();i++){
                if (set.contains(s.substring(index,i))){
                    if (process(s,i,set))
                        return true;
                }
            }
            return false;
    }

    //2dp
    public boolean wordBreak2dp(String s, List<String> wordDict) {
        boolean[] dp=new boolean[wordDict.size()+1];
        HashSet<String> set=new HashSet<>();
        for (String ss:wordDict)
            set.add(ss);
        dp[wordDict.size()]=true;
        for (int i=dp.length-2;i>=0;i--){
            for (int j=i+1;j<s.length();j++){
                if (set.contains(s.substring(i,j))&&dp[j]){
                    dp[i]=true;
                    continue;
                }
            }
        }
        return dp[0];
    }


    public boolean CheckPermutation(String s1, String s2) {
        int[] h1 = s2hash(s1);
        int[] h2 = s2hash(s2);
        for (int i=0;i<h1.length;i++){
            if (h1[i]!=h2[i])
                return false;
        }
        return true;
    }

    public int[] s2hash(String s){
        int[] hash=new int[26];
        for (int i=0;i<s.length();i++)
            hash[s.charAt(i)-'a']++;
        return hash;
    }

    //排序链表

    static class tmp22 {
        public ListNode sortList(ListNode head) {
            if (head == null)
                return head;
            if (head.next == null) {
                return head;
            } else {
                ListNode dummy=new ListNode(-1);
                dummy.next=head;
                ListNode slow = head;
                ListNode fast = head.next;
                while (fast != null && fast.next != null) {
                    slow = slow.next;
                    fast = fast.next.next;
                }
                ListNode nn = slow.next;
                slow.next = null;
                dummy.next=null;
                ListNode l1 = sortList(head);
                ListNode l2 = sortList(nn);
                ListNode res = mergeList(l1, l2);
                return res;
            }
        }

        public ListNode mergeList(ListNode l1,ListNode l2){
            if (l1==null)
                return l2;
            if (l2==null)
                return l1;
            ListNode dummy=new ListNode(-1);
            ListNode ptr=dummy;
            while (l1!=null&&l2!=null){
                if (l1.val<=l2.val){
                    ptr.next=l1;
                    ptr=ptr.next;
                    ListNode t = l1.next;
                    l1.next=null;
                    l1=t;
                }else {
                    ptr.next=l2;
                    ptr=ptr.next;
                    ListNode t2=l2.next;
                    l2.next=null;
                    l2=t2;
                }
            }
            if (l1!=null)
                ptr.next=l1;
            if (l2!=null)
                ptr.next=l2;
            return dummy.next;
        }

    }


    //
    public int candy111(int[] ratings) {
        //at least one candy
        int[] res=new int[ratings.length];
        Arrays.fill(res,1);
        //left->right
        for (int i=1;i<ratings.length;i++){
            if (ratings[i]>ratings[i-1])
                res[i]=res[i-1]+1;
        }
        //right->left
        for (int i=ratings.length-2;i>=0;i--){
            if (ratings[i]> ratings[i+1]){
                res[i]=Math.max(res[i],res[i+1]+1);
            }
        }
        //totoal
        int total=0;
        for (int i:res)
            total+=i;
        return total;
    }

    //

    //1
    //无重复
    public int findMin111(int[] nums) {
        if (nums.length==1)
            return nums[0];
        if (nums[0]<nums[nums.length-1])
            return nums[0];
        if (nums.length==2)
            return Math.min(nums[0],nums[1]);
        int left=0;
        int right=nums.length-1;
        while (left<right){
            int mid=(left+right)/2;
            if (mid==nums.length-1){
                if (nums[mid-1]>nums[mid])
                    return nums[mid];
            }
            if (nums[mid-1]>nums[mid]&&nums[mid+1]>nums[mid])
                return nums[mid];
            if (nums[mid]>nums[0]){
                right=mid;
            }else {
                left=mid;
            }
        }
        return -1;
    }

    //you重复
    public int findMin222(int[] nums) {
        int l=0;
        int r=nums.length-1;
        while (l<r){
            int mid=l+(r-l)/2;
            if (nums[mid]>nums[r]){
                l=mid+1;
            }else if (nums[mid]<nums[r]){
                r=mid;
            }else
                r--;
        }
        return nums[l];
    }

    public int maxPoints222(int[][] points) {
        if (points.length<=2)
            return points.length;
        int res=1;
        for (int i=0;i<points.length;i++){
            HashMap<String,Integer> counts=new HashMap<>();
            int max=0;
            for (int j=i+1;j<points.length;j++){
                    int x1=points[i][0];
                    int x2=points[j][0];
                    int y1=points[i][1];
                    int y2=points[j][1];
                    int z=gcd2(x1-x2,y1-y2);
                    int a=x1-x2;
                    int b=y1-y2;
                    String key=(a/z)+"-"+(b/z);
                    counts.put(key,counts.getOrDefault(key,0)+1);
                    max=Math.max(max,counts.get(key));
            }
            res=Math.max(res,max+1);
        }
        return res;
    }
    public int gcd2(int a,int b){
        return b==0?a:gcd2(b,a%b);
    }


    // 3 5 7
    public int getKthMagicNumber(int k) {
        int[] res=new int[k];
        res[0]=1;
        int i3=0;
        int i5=0;
        int i7=0;
        for (int i=1;i<res.length;i++){
            res[i]=Math.min(res[i3]*3,Math.min(res[i5]*5,res[i7]*7));
            if (res[i]==res[i3]*3)
                i3++;
            if (res[i]==res[i5]*5)
                i5++;
            if (res[i]==res[i7]*7)
                i7++;
        }
        return res[k-1];
    }

    public void reorderList(ListNode head) {
        if (head==null||head.next==null)
            return;
        if (head.next.next==null){
            head.next.next=head;
            head.next=null;
            return;
        }
        ListNode listNode = process4reorderlist(head.next);
        head.next=listNode;
        return;
    }
    public ListNode process4reorderlist(ListNode node){
            if (node.next==null)
                return node;
            if (node.next.next==null){
                ListNode res=node.next;
                node.next.next=node;
                node.next=null;
                return res;
            }
            ListNode ptr=node;
            while (ptr.next.next!=null)
                ptr=ptr.next;
            ListNode res=ptr.next;
            res.next=node;
            ptr.next=null;
            node.next=process4reorderlist(node.next);
            return res;
    }

    //上面的递归，效率很差
    //另一个思路
    /*
    将链表从中间分成两份
    将后面的反转
    将后面的链表插入到前面链表中
     */
    public void reorderList2(ListNode head) {
        if (head==null||head.next==null)
            return ;
        //找到中间节点
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode slow=dummy.next;
        ListNode fast=dummy.next.next;
        while (fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
        }
        //分割链表
        ListNode l1=head;
        dummy.next=null;
        ListNode pre=slow;
        ListNode l2=pre.next;
        pre.next=null;
        //反转l2;
        ListNode l22 = reverse4reodrder(l2);
        //将l2插入到l1;
        while (l1!=null&&l22!=null){
            ListNode l1n=l1.next;
            ListNode l2n=l22.next;
            l1.next=l22;
            l22.next=l1n;
            l1=l1n;
            l22=l2n;
        }
    }
    public ListNode reverse4reodrder(ListNode node){
        ListNode pre=null;
        ListNode cur=node;
        while (cur!=null){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

    public int maxProfit22(int[] prices) {
        int min=prices[0];
        int res=0;
        for (int i=1;i<prices.length;i++){
            res=Math.max(res,prices[i]-min);
            min=Math.min(min,prices[i]);
        }
        return res;
    }


    //腐烂的橘子
    public int orangesRotting(int[][] grid) {
            int count=0;
            while (!allBad(grid)){
                boolean sucess = process(grid);
                if (sucess==false)
                    return -1;
                count++;
            }
            return count;
    }

    public boolean process(int[][] grid){
        int count=0;
        for (int i=0;i<grid.length;i++){
            for (int j=0;j<grid[0].length;j++){
                if (grid[i][j]==2){
                    if (i>0){
                        if (grid[i-1][j]==1) {
                            grid[i - 1][j] = 3;
                            count += 1;
                        }
                    }
                    if (i<grid.length-1){
                        if (grid[i+1][j]==1) {
                            grid[i+1][j] = 3;
                            count += 1;
                        }
                    }
                    if (j>0){
                        if (grid[i][j-1]==1) {
                            grid[i][j-1] = 3;
                            count += 1;
                        }
                    }
                    if (j<grid[0].length-1){
                        if (grid[i][j+1]==1) {
                            grid[i][j+1] = 3;
                            count += 1;
                        }
                    }
                }
            }
        }
        for (int i=0;i<grid.length;i++){
            for (int j=0;j<grid[0].length;j++){
                if (grid[i][j]==3)
                    grid[i][j]=2;
            }
        }
        return count>0;
    }

    public boolean allBad(int[][] grid){
        for (int i=0;i<grid.length;i++){
            for (int j=0;j<grid[0].length;j++){
                if (grid[i][j]==1)
                    return false;
            }
        }
        return true;
    }

    public int findRadius(int[] houses, int[] heaters) {
        Arrays.sort(houses);
        Arrays.sort(heaters);
        int res=0;
        for (int house:houses){
            int index=0;
            while (index< heaters.length&&heaters[index]<=house)
                index++;
            if (index==0)
                res=Math.max(res,heaters[index]-house);
            else if (index==heaters.length)
                res=Math.max(res,house-heaters[index-1]);
            else
                res=Math.max(res,Math.min(house-heaters[index-1],heaters[index]-house));
        }
        return res;
    }

    public boolean isUnique(String astr) {
        int[] hash=new int[26];
        for (int i=0;i<astr.length();i++){
            hash[astr.charAt(i)-'a']++;
            if (hash[astr.charAt(i)-'a']>1)
                return false;
        }
        return true;
    }

    public int findContentChildren(int[] g, int[] s) {
            Arrays.sort(g);
            Arrays.sort(s);
            int index=s.length-1;
            int child=g.length-1;
            int count=0;
            while (index>=0&&child>=0){
                if (s[index]>=g[child]) {
                    count++;
                    index--;
                    count--;
                }else
                    child--;
            }
            return count;
    }

    public List<String> binaryTreePaths(TreeNode root) {
        ArrayList<String> res=new ArrayList<>();
        if (root==null)
            return res;
        process4btp(root,res,"");
        return res;
    }
    public void process4btp(TreeNode node,ArrayList<String> res,String s){
        if(node==null)
            return ;
        if (node.left==null&&node.right==null){
            s=s+node.val;
            res.add(s);
            return;
        }
        process4btp(node.left,res,s+node.val+"->");
        process4btp(node.right,res,s+node.val+"->");
    }

    //71简化路径
    public String simplifyPath(String path) {
        String[] strings = path.split("/");
        Stack<String> stack=new Stack<>();
        for (String s:strings){
            if (s.equals("..")&&!stack.isEmpty())
                stack.pop();
            //这里，!s.equals("")，是因为，在使用split函数的时候，会分割出空串
            if (!s.equals(".")&&!s.equals("..")&&!s.equals(""))
                stack.push(s);
        }
        StringBuilder sb=new StringBuilder();
        while (!stack.isEmpty()){
            sb.insert(0,stack.pop());
            sb.insert(0,"/");
        }
        if (sb.length()==0)
            sb.append("/");
        return sb.toString();
    }

    public String simplifyPath2(String path) {
        String[] strings = path.split("/");
        Stack<String> stack=new Stack<>();
        for (int i=0;i<strings.length;i++){
            if (strings[i].equals("..")&&!stack.isEmpty())
                stack.pop();
            if (!strings[i].equals("")&&!strings[i].equals(".")&&!strings[i].equals(".."))
                stack.push(strings[i]);
        }
        StringBuilder res=new StringBuilder();
        while (!stack.isEmpty()){
            res.insert(0,stack.pop());
            res.insert(0,"/");
        }
        if (res.length()==0)
            res.append("/");
        return res.toString();
    }

    //386 字典序排数
    public List<Integer> lexicalOrder2(int n) {
            //n叉树的先序列遍历
        List<Integer> res=new ArrayList<>();
        for (int i=1;i<=9;i++){
            dfs4_386(i,res,n);
        }
        return res;
    }
    public void dfs4_386(int num,List<Integer> res,int max){
        if (num>max)
            return;
        res.add(num);
        for (int j=num*10;j<=num*10+9;j++)
            dfs4_386(j,res,max);
        return;
    }


    //迭代实现，满足o（1）空间复杂度
    public List<Integer> lexicalOrder(int n) {
        List<Integer> res=new ArrayList<>();
        int base=1;
        while (res.size()<n){
            while (base<=n){
                res.add(base);
                base*=10;
            }
            while (base>n||base%10==9){
                base/=10;
            }
            base+=1;
        }
        return res;
    }


    public int findKthNumber(int n, int k) {
            int base=1;
            int count=1;
            while (count<k){
                int total=count4findKthNumber(base,n);
                if (count+total<=k){
                    base++;
                    count+= total;
                }else {
                    base*=10;
                    count++;
                }
            }
            return base;
    }

    public int count4findKthNumber(int c,int max){
        long cur=c;
        long next=c+1;
        int count=0;
        while (cur<=max){
            count+=(Math.min(next,max+1)-cur);
            cur*=10;
            next*=10;
        }
        return count;
    }

    public int trap22(int[] height) {
        int len=height.length;
        if (len==1)
            return 0;
        int[] leftMAX=new int[len];
        leftMAX[1]=height[0];
        for (int i=2;i<len;i++)
            leftMAX[i]=Math.max(leftMAX[i-1],height[i-1]);
        int[] rightMax=new int[len];
        rightMax[len-2]=height[len-1];
        for (int i=len-3;i>=0;i--)
            rightMax[i]=Math.max(rightMax[i+1],height[i+1]);
        int res=0;
        for (int i=0;i<len-1;i++){
            res+=Math.max(0,Math.min(rightMax[i],leftMAX[i])-height[i]);
        }
        return res;
    }

    public ListNode reverseKGroup333(ListNode head, int k) {
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode pre=dummy;
        ListNode cur=dummy;
        while(cur.next!=null){
            for (int i=1;i<=k&&cur!=null;i++)
                cur=cur.next;
            if (cur==null)
                return dummy.next;
            ListNode next=cur.next;
            cur.next=null;
            ListNode ntail=pre.next;
            pre.next=null;
            ListNode nh = rev4(ntail);
            pre.next=nh;
            ntail.next=next;
            pre=nh;
            cur=pre;
        }
        return dummy.next;
    }

    public ListNode rev4(ListNode node){
        if (node==null||node.next==null)
            return node;
        ListNode tail=node.next;
        ListNode res = rev4(node.next);
        tail.next=node;
        node.next=null;
        return res;
    }

    //找到第k大
    public int findKthLargest2(int[] nums, int k) {
        //第k大就是第nums.length-k+1小
        int ksmall=nums.length-k+1;
        return quickSort4k(nums,0,nums.length-1,ksmall);
    }
    //在l..r范围内找第k小
    public int quickSort4k(int[] nums,int l,int r,int k){
        int pos = paration4kk(nums, l, r);
        int size=pos-l+1;
        if (size==k){
            return nums[pos];
        }else if (size<k){
            return quickSort4k(nums,pos+1,r,k-size);
        }else
            return quickSort4k(nums,l,r,k);
    }

    public int paration4kk(int[] nums,int l,int r){
        int standard=nums[r];
        int lbound=l-1;
        int index=l;
        while (index<r){
            if (nums[index]<standard){
                lbound++;
                int tmp=nums[lbound];
                nums[lbound]=nums[index];
                nums[index]=tmp;
                index++;
            }else
                index++;
        }
        int pos=lbound+1;
        int tmp2=nums[pos];
        nums[pos]=nums[r];
        nums[r]=tmp2;
        return pos;
    }


    static class TireNode2{
        TireNode2[] nexts=new TireNode2[26];
        int pass=0;
        int end=0;
        String ss;

        TireNode2(){}


        public  void insertTireNode(TireNode2 root,String s){
            TireNode2 ptr=root;
            char[] chars = s.toCharArray();
            for (int i=0;i<chars.length;i++){
                int index=chars[i]-'a';
                if (ptr.nexts[index]==null)
                    ptr.nexts[index]=new TireNode2();
                ptr=ptr.nexts[index];
                if (i==chars.length-1) {
                    ptr.end++;
                    ptr.ss=s;
                }
                else
                    ptr.pass+=1;
            }
        }
    }


    public List<String> findWords(char[][] board, String[] words) {
            TireNode2 root=new TireNode2();
            for (String s:words)
                root.insertTireNode(root,s);
            List<String> res=new ArrayList<>();
            for (int i=0;i<board.length;i++){
                for (int j=0;j<board[0].length;j++){
                    if (root.nexts[board[i][j]-'a']!=null) {
                        boolean[][] visited=new boolean[board.length][board[0].length];
                        dfs4_findWords(board, i, j, visited,res,root);
                    }
                }
            }
            return res;
    }

    public void dfs4_findWords(char[][] board,int x,int y,boolean[][] visited,List<String> res,TireNode2 root){
            if (x>=board.length||x<0||y>= board[0].length||y<0)
                return;
            if (visited[x][y])
                return;
            if (root.nexts[board[x][y]-'a']==null)
                return;
            visited[x][y]=true;
            TireNode2 tmp=root.nexts[board[x][y]-'a'];
            if (tmp.end>0) {
                res.add(tmp.ss);
                tmp.end--;
            }
            dfs4_findWords(board,x-1,y,visited,res,tmp);
            dfs4_findWords(board,x+1,y,visited,res,tmp);
            dfs4_findWords(board,x,y-1,visited,res,tmp);
            dfs4_findWords(board,x,y+1,visited,res,tmp);
            visited[x][y]=false;
    }

    public int[] findOrder(int numCourses, int[][] prerequisites) {
            Queue<int[]> queue=new LinkedList<>();
            for (int[] arr:prerequisites)
                queue.offer(arr);
            int[] counts=new int[numCourses];
            for (int i=0;i<prerequisites.length;i++){
                counts[prerequisites[i][0]]++;
            }
            List<Integer> res=new LinkedList<>();
             for (int i=0;i<counts.length;i++){
                if (counts[i]==0)
                res.add(i);
             }
            while (!queue.isEmpty()){
                int size=queue.size();
                for (int i=0;i<size;i++){
                    int[] poll = queue.poll();
                    if (counts[poll[1]]==0) {
                        counts[poll[0]]--;
                        if (counts[poll[0]]==0)
                            res.add(poll[0]);
                    }
                    else
                        queue.offer(poll);
                }
                if (size==queue.size())
                    return new int[]{};
            }
            int[] resarr=new int[numCourses];
            for (int i=0;i<resarr.length;i++)
                resarr[i]=res.get(i);
            return resarr;
    }

    public int countPrimes(int n) {
        int[] nums=new int[n];
        Arrays.fill(nums,1);
        int res=0;
        for (int i=2;i<nums.length;i++){
            res+=nums[i];
            if (nums[i]==1){
                for (int j=2;j*i<n;j++)
                    nums[i*j]=0;
            }
        }
        return res;
    }

    public boolean isPrime(int num){
        for (int i=2;i<num;i++){
            if (num%i==0)
                return false;
        }
        return true;
    }

    public int minAddToMakeValid(String s) {
        int needR=0;
        int needL=0;
        for (int i=0;i<s.length();i++){
            if (s.charAt(i)=='(')
                needR++;
            else {
                if (needR>0)
                    needR--;
                else
                    needL++;
            }
        }
        return needR+needL;
    }

    public void rotate(int[] nums, int k) {
        int len=nums.length;
        //actual move times
        int rk=k%len;
        reverse4rotate(nums,0,len-1);
        reverse4rotate(nums,0,rk-1);
        reverse4rotate(nums,rk,len-1);
    }

    public void reverse4rotate(int[] nums,int l,int r){
        while (l<r){
            int tmo=nums[l];
            nums[l]=nums[r];
            nums[r]=tmo;
            l++;
            r--;
        }
    }

    public int titleToNumber(String columnTitle) {
            //26进制
        char[] chars = columnTitle.toCharArray();
        int res=0;
        for (int i=0;i<chars.length;i++){
            int tmp=chars[i]-'A'+1;
            res=res*26+tmp;
        }
        return res;
    }

    public int trailingZeroes(int n) {
        int count=0;
        while (n>0){
            count+=n/5;
            n/=5;
        }
        return count;
    }

    public String fractionToDecimal(int numerator, int denominator) {
        StringBuilder sb=new StringBuilder();
        if ((numerator<0&&denominator>0)||(numerator>0&&denominator<0))
            sb.append("-");
        long n=Math.abs((long)numerator);
        long d=Math.abs((long)denominator);
        sb.append(n/d);
        if (n%d!=0)
            sb.append(".");
        else
            return sb.toString();
        HashMap<Long,Integer> map=new HashMap<>();
        while ((n=(n%d)*10)!=0&&!map.containsKey(n)){
            map.put(n,sb.length());
            sb.append(n/d);
        }
        if (n==0)
            return sb.toString();
        return sb.insert(map.get(n).intValue(),'(').append(')').toString();
    }



    int count4kth;
    int res4kth;
    public int kthSmallest(TreeNode root, int k) {
            process4kths(root,k);
            return res4kth;
    }

    public void process4kths(TreeNode node,int k){
        if (node==null)
            return;
        process4kths(node.left,k);
        count4kth++;
        if (count4kth==k){
            res4kth=node.val;
            return;
        }
        process4kths(node.right,k);
    }

    public boolean isAnagram(String s, String t) {
        int[] h1=new int[26];
        int[] h2=new int[26];
        fiill_hash(h1,s);
        fiill_hash(h2,t);
        for (int i=0;i<26;i++){
            if (h1!=h2)
                return false;
        }
        return true;
    }

    public void fiill_hash(int[] arr,String s){
        for (int i=0;i<s.length();i++)
            arr[s.charAt(i)-'a']++;
    }

    //227 基本计算器
    public int calculate222(String s) {
        /*Stack<Character> stack=new Stack<>();
        for (int i=0;i<s.length();i++){
            if (s.charAt(i)==' '){
            }else if (Character.isDigit(s.charAt(i))){
                stack.push(s.charAt(i));
            }else if (s.charAt(i)=='-'||s.charAt(i)=='+')
                stack.push(s.charAt(i));
            else {
                int op1 = stack.pop()-'0';
                int index=i+1;
                while (s.charAt(index)==' ')
                    index++;
                int op2=s.charAt(index)-'0';
                int tmp=0;
                if (s.charAt(i)=='*'){
                    tmp=op1*op2;
                }else
                    tmp=op1/op2;
                stack.push((tmp+"").charAt(0));
                i=index;
            }
        }
        while (stack.size()!=1){
            int op1 = stack.pop()-'0';
            Character op = stack.pop();
            int op2 = stack.pop()-'0';
            int tmp=0;
            if (op=='+'){
                tmp=op1+op2;
            }else
                tmp=op1-op2;
            stack.push(String.valueOf(tmp).charAt(0));
        }
        return (int)stack.peek();*/

        /*Stack<Integer> stack=new Stack<>();
        Character preop='+';
        int num=0;
        for (int i=0;i<s.length();i++){
            if (Character.isDigit(s.charAt(i)))
                num=num*10+s.charAt(i)-'0';
            if (!Character.isDigit(s.charAt(i))&&s.charAt(i)!=' '||i==s.length()-1){
                switch(preop){
                    case '+':
                        stack.push(num);
                        break;
                    case '-':
                        stack.push(-num);
                        break;
                    case '*':
                        stack.push(stack.pop()*num);
                        break;
                    case '/':
                        stack.push(stack.pop()/num);
                        break;
                }
                preop=s.charAt(i);
                num=0;
            }
        }
        int res=0;
        while (!stack.isEmpty()){
            res+=stack.pop();
        }
        return res;*/
        return 0;
    }

    public int calculate22222(String ss) {
        String s = ss.replaceAll(" ", "");
        Stack<Integer> stack=new Stack<>();
        Character preop='+';
        int num=0;
        for (int i=0;i<s.length();i++){
            if (Character.isDigit(s.charAt(i)))
                num=num*10+s.charAt(i)-'0';
            if (!Character.isDigit(s.charAt(i))||i==s.length()-1){
                char op = preop;
                if (op=='+'){
                    stack.push(num);
                }else if (op=='-'){
                    stack.push(-num);
                }else if (op=='*'){
                    stack.push(stack.pop()*num);
                }else if (op=='/'){
                    stack.push(stack.pop()/num);
                }
                num=0;
                preop=s.charAt(i);
            }
        }
        int res=0;
        while (!stack.isEmpty())
            res+=stack.pop();
        return res;
    }

    public int calculate224(String s) {
        Stack<Integer> stack=new Stack<>();
        int op=1;
        int res=0;
        for (int i=0;i<s.length();i++){
            if (Character.isDigit(s.charAt(i))){
                int cur=s.charAt(i)-'0';
                while (i+1<s.length()&&Character.isDigit(s.charAt(i+1))) {
                    i++;
                    cur=cur*10+s.charAt(i)-'0';
                }
                res=res+op*cur;
            }else {
                if (s.charAt(i)=='+'){
                    op=1;
                }else if (s.charAt(i)=='-'){
                    op=-1;
                }else if (s.charAt(i)=='('){
                    stack.push(res);
                    stack.push(op);
                    res=0;
                    op=1;
                }else if (s.charAt(i)==')'){
                    int opp=stack.pop();
                    int prenum=stack.pop();
                    res=res*opp+prenum;
                }
            }
        }
        return res;
    }


    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
            //分组+hashmap，具体看题解，思路并不难
            HashMap<Integer,Integer> ab=new HashMap<>();
            for (int i=0;i<nums1.length;i++){
                for (int j=0;j<nums2.length;j++){
                    int summ=nums1[i]+nums2[j];
                    ab.put(summ,ab.getOrDefault(summ,0)+1);
                }
            }
            int count=0;
            for (int i=0;i<nums3.length;i++){
                for (int j=0;j<nums4.length;j++){
                    int summm=nums3[i]+nums4[j];
                    count+=ab.getOrDefault(-summm, 0);
                }
            }
            return count;
    }



    //去重是关键！
    //四数之和
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res=new ArrayList<>();
        if (nums.length<4)
            return res;
        Arrays.sort(nums);
        long ltarget=(long)target;
        for (int i=0;i<nums.length-3;i++){
            if (i>0&&nums[i]==nums[i-1])
                continue;
            for (int j=i+1;j<nums.length-2;j++){
                if (j>i+1&&nums[j]==nums[j-1])
                    continue;
                long tat=ltarget-nums[i]-nums[j];
                int left=j+1;
                int right=nums.length-1;
                while (left<right){
                    long cur=nums[left]+nums[right];
                    if (tat==cur){
                        ArrayList<Integer> tmp=new ArrayList<>();
                        tmp.add(nums[i]);
                        tmp.add(nums[j]);
                        tmp.add(nums[left]);
                        tmp.add(nums[right]);
                        res.add(tmp);
                        left++;
                        right--;
                        while (left<right&&nums[left]==nums[left-1])
                            left++;
                        while (left<right&&nums[right]==nums[right+1])
                            right--;
                    }else if (cur<tat){
                        left++;
                    }else
                        right--;
                }
            }
        }
        return res;
    }

    //三数字之和
    public List<List<Integer>> threeSum22(int[] nums) {
            List<List<Integer>> res=new ArrayList<>();
            if (nums.length<3)
                return res;
            Arrays.sort(nums);
            for (int i=0;i<nums.length-2;i++){
                if (nums[i]>0)
                    break;
                else if (i>0&&nums[i]==nums[i-1])
                    continue;
                else {
                    int target=0-nums[i];
                    int left=i+1;
                    int right=nums.length-1;
                    while (left<right){
                        int leftval=nums[left];
                        int rightval=nums[right];
                        if (leftval+rightval==target){
                            List<Integer> tmp=new ArrayList<>();
                            tmp.add(nums[i]);
                            tmp.add(leftval);
                            tmp.add(rightval);
                            res.add(tmp);
                            left++;
                            right--;
                            while (left<right&&nums[left]==nums[left-1])
                                left++;
                            while (left<right&&nums[right]==nums[right+1])
                                right--;
                        }else if (leftval+rightval<target)
                            left++;
                        else
                            right--;
                    }
                }
            }
            return res;
    }


    //自己写的 不太对
    public int longestSubstring2(String s, int k) {
        /*int[] hash=new int[26];
        int gap=0;
        int start=0;
        int res=0;
        for (int i=0;i<s.length();i++){
            int tmp = s.charAt(i)-'a';
            hash[tmp]++;
            if (hash[tmp]==k){
                gap--;
            }else if (hash[tmp]>k){

            }else {
                if (hash[tmp]==1)
                    gap++;
            }
            if (gap==0) {
                res = Math.max(res, i - start + 1);
                hash[start]--;
                if (hash[start]>=k){
                }else if (hash[start]==k-1)
                    gap++;
            }
        }
        return res;*/
        return 0;
    }

    //这个题很妙！
    //至少有k个重复字符的最长子串
    public int longestSubstring(String s, int k) {
        if (s.length()<k)
            return 0;
        HashMap<Character,Integer> map=new HashMap<>();
        for (int i=0;i<s.length();i++)
            map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1);
        int res=0;
        for (Character c:map.keySet()){
            if (map.get(c)<k){
                String[] splits = s.split(c+"");
                for (String ss:splits)
                    res=Math.max(res,longestSubstring(ss,k));
                return res;
            }
        }
        return s.length();
    }

    public int firstUniqChar(String s) {
            int[] hash=new int[26];
            for (int i=0;i<s.length();i++)
                hash[s.charAt(i)-'a']++;
            for (int i=0;i<s.length();i++){
                if (hash[s.charAt(i)-'a']==1)
                    return i;
            }
            return -1;
    }

    public int search_ez(int[] nums, int target) {
            int l=0;
            int r=nums.length-1;
            while (l<=r){
                int mid=l+(r-l)/2;
                if (nums[mid]==target)
                    return mid;
                else if (nums[mid]>target){
                    r=mid--;
                }else
                    l=mid++;
            }
            return l;
    }

    public TreeNode lowestCommonAncestor222(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode res = findAncastor(root, p, q);
        return res;
    }

    public TreeNode findAncastor(TreeNode root,TreeNode t1,TreeNode t2){
        if (root==null)
            return null;
        if (root==t1||root==t2)
            return root;
        TreeNode l = findAncastor(root.left, t1, t2);
        TreeNode r = findAncastor(root.right, t1, t2);
       if (l!=null&&r!=null)
           return root;
       if (l==null)
           return r;
       if (r==null)
           return l;
       return null;

    }




    int res4maxPathSum222;
    public int maxPathSum22222(TreeNode root) {
        preocess4maxPathSum(root);
        return res4maxPathSum222;
    }

    //返回的是node，或者node+左/node+右 的三个路径中最大的那个，给上面的父节点用
    //并且在这个函数中，更新结果的值
    public int preocess4maxPathSum(TreeNode node){
        if (node==null)
            return 0;
        int l = preocess4maxPathSum(node.left);
        int r = preocess4maxPathSum(node.right);
        if (l>=0&&r>=0){
            res4maxPathSum222=Math.max(res4maxPathSum222,l+r+node.val);
            return Math.max(l,r)+node.val;
        }else if (l>=0&&r<=0){
            res4maxPathSum222=Math.max(res4maxPathSum222,l+node.val);
            return l+node.val;
        }else if(r<=0&&r>=0){
            res4maxPathSum222=Math.max(res4maxPathSum222,r+node.val);
            return r+node.val;
        }else {
            res4maxPathSum222=Math.max(res4maxPathSum222,node.val);
            return node.val;
        }

    }

    public int lengthOfLongestSubstring2222222(String s) {
        HashMap<Character,Integer> map=new HashMap<>();
        int maxlen=0;
        int curlen=0;
        for (int i=0;i<s.length();i++){
            if (!map.containsKey(s.charAt(i))){
                curlen++;
                map.put(s.charAt(i),i);
            }else {
                int lastindex=map.get(s.charAt(i));
                if (i-lastindex>=curlen){
                    curlen++;
                }else {
                    curlen=i-lastindex;
                }
                map.put(s.charAt(i),i);
            }
            maxlen=Math.max(maxlen,curlen);
        }
        return maxlen;
    }


    ArrayList<Integer> res4dfo=new ArrayList<>();
    public int[] findDiagonalOrder(int[][] mat) {
            int x1=0;
            int y1=0;
            int x2=0;
            int y2=0;
            boolean up2down=false;
            while (y1<mat[0].length&&x2<mat.length){
                process4fdo(mat,x1,y1,x2,y2,up2down);
                up2down=!up2down;
                if (x1!=mat.length-1){
                    x1++;
                }
                if (x1==mat.length-1){
                    y1++;
                }
                if (y2!=mat[0].length-1)
                    y2++;
                if (y2==mat[0].length-1)
                    x2++;
            }
            int[] res=new int[res4dfo.size()];
            for (int i=0;i<res.length;i++)
                res[i]=res4dfo.get(i);
            return res;
    }

    public void process4fdo(int[][] mat,int x1,int y1,int x2,int y2,boolean up2down){
        int[] tmp=new int[x1-x2+1];
        int index=0;
        while (x1>=x2){
            tmp[index]=mat[x1][y1];
            x1--;
            y1++;
            index++;
        }
        if (up2down){
            for (int i=tmp.length-1;i>=0;i--)
                res4dfo.add(tmp[i]);
        }else {
            for (int i=0;i<tmp.length;i++)
                res4dfo.add(tmp[i]);
        }
    }

    public int[] advantageCount(int[] nums1, int[] nums2) {
        int len=nums1.length;
        Integer[] idx1=new Integer[len];
        Integer[] idx2=new Integer[len];
        for (int i=0;i<len;i++){
            idx1[i]=i;
            idx2[i]=i;
        }
        Arrays.sort(idx1,(i1,i2)->nums1[i1]-nums1[i2]);
        Arrays.sort(idx2,(i1,i2)->nums2[i1]-nums2[i2]);
        int[] ans=new int[len];
        int l=0;
        int r=len-1;
        for (int i=0;i<len;i++){
            if (nums1[idx1[i]]>nums2[idx2[l]]){
                ans[idx2[l]]=nums1[idx1[i]];
                l++;
            }else {
                ans[idx2[r]]=nums1[idx1[i]];
                r--;
            }
        }
        return ans;
    }


    //meituan chong!!!jiayou ! guoguogguo!!!!!

    public ListNode detectCyclemeituan(ListNode head) {
            if (head.next==null||head.next.next==null)
                return null;
            ListNode fast=head.next.next;
            ListNode slow=head.next;
            while (fast!=null&&fast.next!=null&&fast.next.next!=null&&fast!=slow){
                fast=fast.next.next;
                slow=slow.next;
            }
            if (fast==null||fast.next==null|| fast.next.next==null)
                return null;
            ListNode res=head;
            while (res!=slow){
                slow=slow.next;
                res=res.next;
            }
            return res;
    }


    public int longestConsecutivemeituan(int[] nums) {
        HashSet<Integer> set=new HashSet<>();
        for (int i:nums)
            set.add(i);
        int max=0;
        for (int i=0;i<nums.length;i++){
            if (set.contains(nums[i]-1))
                continue;
            else {
                int count=1;
                int tmp=nums[i]+1;
                while (set.contains(tmp)){
                    tmp++;
                    count++;
                }
                max=Math.max(max,tmp);
            }
        }
        return max;
    }

    public String multiply(String num1, String num2) {
            if (num1.equals("0")||num2.equals("0"))
                return "0";
            String res="0";
            int m=num1.length();
            int n=num2.length();
            //num2的各个位依次和num1相乘
            for (int i=n-1;i>=0;i--){
                StringBuilder tmp=new StringBuilder();
                //每高一位，要多一个0
                for (int j=n-1;j>i;j--)
                    tmp.append("0");
                //模拟相乘
                int add=0;
                int cur=num2.charAt(i)-'0';
                for (int j=m-1;j>=0;j--){
                    int t=cur*(num1.charAt(j)-'0')+add;
                    tmp.append(t%10);
                    add=t/10;
                }
                if (add!=0)
                    tmp.append(add);
                tmp.reverse();
                //模拟各个位乘完的结果相加
                res=add2num(res,tmp.toString());
            }
            return res;
    }

    /**
     *
     *  4 5 6
     *  7 8 9
     */
    public String add2num(String s1,String s2){
        StringBuilder sb=new StringBuilder();
        int add=0;
        int m=s1.length()-1;
        int n=s2.length()-1;
        //感觉这个while的条件写的很好，比自己写的优雅很多！
        while (m>=0||n>=0||add>0){
            int add1=m>=0?s1.charAt(m)-'0':0;
            int add2=n>=0?s2.charAt(n)-'0':0;
            int tmp=add1+add2+add;
            sb.append(tmp%10);
            add=tmp/10;
            m--;
            n--;
        }
        sb.reverse();
        return sb.toString();
    }


    public ListNode reverseBetweenmt(ListNode head, int left, int right) {
        if(head==null||head.next==null)
            return head;
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode l=dummy;
        ListNode r=dummy;
        for (int i=0;i<left-1;i++)
            l=l.next;
        for (int j=0;j<right;j++)
            r=r.next;
        ListNode nxt=r.next;
        ListNode pre=l;
        ListNode ntail=pre.next;
        pre.next=null;
        r.next=null;
        ListNode nhead = reverse_meituan(ntail);
        pre.next=nhead;
        ntail.next=nxt;
        return dummy.next;
    }

    public ListNode reverse_meituan(ListNode node){
        if (node==null||node.next==null)
            return node;
        ListNode pre=null;
        ListNode cur=node;
        while (cur!=null){
            ListNode n=cur.next;
            cur.next=pre;
            pre=cur;
            cur=n;
        }
        return pre;
    }

    public int search_meituan(int[] nums, int target) {
        int l=0;
        int r=nums.length-1;
        while (l<=r){
            int mid=l+(r-l)/2;
            if (nums[mid]==target)
                return mid;
            if (nums[mid]<nums[r]){
                if (nums[mid]<target&&nums[r]>target)
                    l=mid+1;
                else
                    r=mid-1;
            }else {
                if (nums[mid]>target&&nums[l]<target)
                    r=mid-1;
                else
                    l=mid+1;
            }
        }
        return -1;
    }



    public int[] sortArray(int[] nums) {
        quicksortmt(nums,0,nums.length-1);
        return nums;
    }

    public void quicksortmt(int[] nums,int l,int r){
        if(l<r){
            int random=l+new Random().nextInt(r-l);
            int tmp=nums[random];
            nums[random]=nums[r];
            nums[r]=tmp;
            int paration = paration(nums, l, r);
            quicksortmt(nums,l,paration-1);
            quicksortmt(nums,paration+1,r);
        }
    }

    public int paration(int[] nums,int l,int r){
        if (l==r)
            return l;
        int lbound=l-1;
        int index=l;
        while (index<r){
            if (nums[index]<=nums[r]){
                lbound++;
                int tmp=nums[lbound];
                nums[lbound]=nums[index];
                nums[index]=tmp;
                index++;
            }else
                index++;
        }
        int res=lbound+1;
        int tmp=nums[res];
        nums[res]=nums[r];
        nums[r]=tmp;
        return res;
    }


    public int longestCommonSubsequence_mt(String text1, String text2) {
            int[][] dp=new int[text1.length()+1][text2.length()+1];
            for (int i=1;i<dp.length;i++){
                for (int j=1;j<dp[0].length;j++){
                    if (text1.charAt(i-1)==text2.charAt(j-1))
                        dp[i][j]=dp[i-1][j-1]+1;
                    dp[i][j]=Math.max(Math.max(dp[i-1][j],dp[i][j-1]),dp[i][j]);
                }
            }
            return dp[dp.length-1][dp[0].length-1];
    }


    class inter{
        int start;
        int end;

        inter(int s,int e){
            this.start=s;
            this.end=e;
        }

    }
    public int[][] mergemt(int[][] intervals) {
            PriorityQueue<inter> priorityQueue=new PriorityQueue<inter>((i1,i2)->{
                if (i1.start==i2.start)
                    return i1.end-i2.end;
                else
                    return i1.start-i2.start;
            });
            for (int i=0;i<intervals.length;i++){
                inter tmp=new inter(intervals[i][0],intervals[i][1]);
                priorityQueue.offer(tmp);
            }

            ArrayList<inter> res=new ArrayList<>();
            while (!priorityQueue.isEmpty()){
                inter poll = priorityQueue.poll();
                while (!priorityQueue.isEmpty()&&poll.end>=priorityQueue.peek().start){
                    inter poll2 = priorityQueue.poll();
                    poll.start=poll.start;
                    poll.end=Math.max(poll.end,poll2.end);
                }
                res.add(poll);
            }
            int[][] resarr=new int[res.size()][2];
            for (int i=0;i<resarr.length;i++){
                resarr[i][0]=res.get(i).start;
                resarr[i][1]=res.get(i).end;
            }
            return resarr;
    }


    public List<List<Integer>> subsets2(int[] nums) {
        return dfs4subsets(nums,0);
    }

    public List<List<Integer>> dfs4subsets(int[] nums,int index){
        if (index==nums.length) {
            List<List<Integer>> res=new ArrayList<>();
            res.add(new ArrayList<>());
            return res;
        }
        List<List<Integer>> res=new ArrayList<>();
        List<List<Integer>> lists = dfs4subsets(nums, index + 1);
        for (int i=0;i<lists.size();i++) {
            res.add(lists.get(i));
            ArrayList<Integer> tmp=new ArrayList<>(lists.get(i));
            tmp.add(nums[index]);
            res.add(tmp);
        }
        return res;
    }


    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        res.add(new ArrayList<>());
        for (int i=0;i<nums.length;i++){
            int size=res.size();
            for (int j=0;j<size;j++){
                ArrayList<Integer> tmp=new ArrayList<>(res.get(j));
                tmp.add(nums[i]);
                res.add(tmp);
            }
        }
        return res;
    }


    public int findLength(int[] nums1, int[] nums2) {
        int m=nums1.length;
        int n=nums2.length;
        int[][] dp=new int[m+1][n+1];
        int max=0;
        for (int i=1;i<m;i++){
            for (int j=1;j<n;j++){
                if (nums1[i-1]==nums2[j-1])
                    dp[i][j]=dp[i-1][j-1]+1;
                else
                    dp[i][j]=0;
                max=Math.max(max,dp[i][j]);
            }
        }
        return max;
    }

    public String minWindow2(String s, String t) {
        HashMap<Character,Integer> map=new HashMap<>();
        for (int i=0;i<t.length();i++)
            map.put(t.charAt(i),map.getOrDefault(t.charAt(i),0)+1);
        int diff=t.length();
        int start=-1;
        int minlen=Integer.MAX_VALUE;
        int left=0;
        int right=0;
        while (right<s.length()){
            map.put(s.charAt(right),map.getOrDefault(s.charAt(right),0)-1);
            if (map.get(s.charAt(right))>=0)
                diff--;
            if (diff==0){
                while (left<right&&map.get(s.charAt(left))<0){
                    map.put(s.charAt(left),map.get(s.charAt(left))+1);
                    left++;
                }
                minlen=Math.min(minlen,right-left+1);
                if (minlen==right-left+1)
                    start=left;
                //强制移动
                left++;
                diff++;
                map.put(s.charAt(left-1),map.get(s.charAt(left-1))-1);
            }
            right++;
        }
        if (start==-1)
            return "";
        return s.substring(left,left+minlen);
    }

    //美团二面完，摆了几天，国庆七天复习的东西，还有刷的算法，一点都没考
    //问的都是面试官所谓的 结合实际的 不明所以的问题， 可恶啊，运气差，也是自己太菜了吧！



    //继续加油吧！







        public static void main(String[] args) {
        new al().subsets(new int[]{1,2,3});
        //new al().sortArray(new int[]{5,1,1,2,0,0});
        //new al().multiply("2","3");
        //new al().findDiagonalOrder(new int[][]{{1,2,3},{4,5,6},{7,8,9}});
        //new al().fourSum(new int[]{2,2,2,2,2},8);
        //System.out.println(new al().calculate22222(" 3/2 "));


        /*
         * <p>Note that if the argument is equal to the value of
         * {@link Integer#MIN_VALUE}, the most negative representable
         * {@code int} value, the result is that same value, which is
         * negative.
         */
        //jdk源码写的，如果对于Integer.MIN_VALUE, 取了绝对值之后，还是本身。
        //System.out.println(Math.abs(-2147483648));

       // new al().fractionToDecimal(-1,-2147483648);
       // int zy = new al().titleToNumber("ZY");
        //System.out.println(zy);
        //new al().findKthLargest2(new int[]{3,2,1,5,6,4},2);
        //int kthNumber = new al().findKthNumber(681692778, 351251360);
       //    System.out.println(kthNumber);
        //new al().simplifyPath2("/home/");
        //new al().simplifyPath("/home/");
        //int[][] tmp={{1,1},{2,2},{3,3}};
        //new al().maxPoints222(tmp);
        //new al().findMin222(new int[]{3,1,3});
        /*ListNode head= new ListNode(4);
        head.next=new ListNode(2);
        head.next.next=new ListNode(1);
        head.next.next.next=new ListNode(3);
        new tmp22().sortList(head);
        new al().missingTwo(new int[]{1, 2, 3, 4, 6, 7, 9, 10});*/

        //int i = new al().minDistance("horse", "rose");
        //System.out.println(i);
        /*String s="leetcode";
        List<String> worddict=new ArrayList<>();
        worddict.add("leet");
        worddict.add("code");
        new al().wordBreak139(s,worddict);*/

       // new al().jump_tx(new int[]{1,2,1,1,1});
        //int[] test=new int[]{2, 2, 2, 3, 3, 5, 5, 5, 6};
        //new al().removeDuplicates(test);
        //printArr(test);
        //new al().lengthOfLIS300(new int[]{1,3,6,7,9,4,10,5,6});
        //new al().solve130(new char[][]{{'X','O'},{'O','X'}});
        //new al().solve130(new char[][]{{'X','X','X','X'},{'X','O','O','X'},{'X','X','O','X'},{'X','O','X','X'}});
        //new al().isPalindrome("OP");
        //new al().generate(5);
        // ListNode listNode=new ListNode(1);
        //new al().removeNthFromEnd555(listNode,1);
        //System.out.println(new al().longestPalindrome6666("babad"));
        // System.out.println(new al().minWindow2("ADOBECODEBANC","ABC"));
        //System.out.println(new al().numDecodings2("11111111111111111111111111111111111"));
        //System.out.println(new al().numDecodings_dp("111111111111111111111111111111111111"));
        //System.out.println(new al().numDecodings("111111111111111111111111111111111111"));
        //System.out.println(new al().numDecodings("111111111111111111111111111111111111"));
        //System.out.println(new al().isMatch44("aa","*"));
        //System.out.println(new al().isMatch44("bbbbbbbabbaabbabbbbaaabbabbabaaabbababbbabbbabaaabaab",
        //        "b*b*ab**ba*b**b***bba"));
        //System.out.println(new al().isMatch44_dp("bbbbbbbabbaabbabbbbaaabbabbabaaabbababbbabbbabaaabaab",
         //       "b*b*ab**ba*b**b***bba"));
       // new al().divide(10,3);
        //new al().lengthOfLongestSubstring555("abcabcbb");
       // new al().isMatch22("ab",".*c");
        //System.out.println(new al().myAtoi("9223372036854775808"));
        //new al().canCompleteCircuit(new int[]{5,8,2,8},new int[]{6,5,6,6});
        //new al().longestPalindrome2("ac");
        //new al().longestCommonSubString("ab1234ua4567ubgbsa","okdo1234567ubgihas");
        //new al().longestCommonSubString2("ab1234ua4567ubgbsa","okdo1234567ubgihas");
        //System.out.println(new al().jump(new int[]{2,3,1,1,4}));
        //new al().dailyTemperatures(new int[]{73,74,75,71,69,72,76,73});
        //new al().findUnsortedSubarray(new int[]{2,4,6,8,1,13,7,9,12,14,15});
        //new al().subarraySum1(new int[]{1},0);
        //new al().duplicateZeros(new int[]{0,0,0,0,0,0,0});
        //new al().change(10,new int[]{10});
        //new al().coinChange4(new int[]{1},0);
        //new al().findAnagrams2("cbaebabacd"
         //       ,"abc");
        //new al().findDisappearedNumbers(new int[]{4,3,2,7,8,2,3,1});
        //String res=new al().decodeString("3[a]2[bc]");
        //new al().topKFrequent(new int[]{1,1,1,2,2,3},2);
        //new al().coinChange(new int[]{2},3);
        //new al().maxProfit_cold(new int[]{1,2,3,0,2});
        //new al().lengthOfLongestSubstring5("abcabcbb");
        //new al().findDuplicate_(new int[]{1,3,4,2,2});
        //System.out.println(new al().numSquares(4));
       /* ListNode head=new ListNode(1);
        head.next=new ListNode(2);
        head.next.next=new ListNode(2);
        head.next.next.next=new ListNode(1);
        new al().isPalindrome(head);*/
        //new al().lengthOfLIS3(new int[]{10,9,2,5,3,4});
       // new al().buildTree(new int[]{3,9,20,15,7},new int[]{9,3,15,20,7});
        //new al().sortColors(new int[]{2,0,2,1,1,0});
        //new al().combinationSum(new int[]{2,3,5},8);
        //new al().searchRange(new int[]{5,7,7,8,8,10},8);
        //new al().nextPermutation(new int[]{2,3,1});
        //new al().search44(new int[]{4,5,6,7,0,1,2},0);
        //new al().generateParenthesis4(3);
       // new al().threeSum_leetcode(new int[]{0,0,0});
        //new al().lengthOfLIS(new int[]{3,5,6,2,5,4,19,5,6,7,12});
        //  new al().solve88("9","99999999999999999999999999999999999999999999999999999999999994");
        //new al().minWindow("XDOYEZODEYXNZ","XYZ");
        /*String s = LCS2("JGIHa76X06Mx330MtfiNafgpQfj0sJVop2nrMb7Gx2i3RIA72UIIXWA2NoPjRN1jwMNVawJrsn3obxhKDINaHLMJT4JnxHo43xf7CUjh77Pae1UUi3GIiH4ponfV6HRzbk1pp7ehACa2ephI6kVb46FR0irx4tVmDjpks0VRonMe3keeVJ83Z8N2eUJoIN4WGd0GQWDn1jnM4MsojgFIbXs7Nu3jnFHrWi3fbNiWRIfxUzr23yb4NGrj1XhkJMbj42DXeUAeifpMNHFx6AGu962ATDV3kkJfAjeJj4Xs0oxq4pGxm2xrrZf4MGJfin4boMzhNFrYGf3sRpafUXIOUAkfU7bas2pHkViihorlhwd7njxefBMpnCWR4rqX76GrW27R1HIna09Dhkfirtpn1F6A2Gr4rbc3MFrtzVrfCxntVh3nHra0I4xNaWi7bVphjoIiGWhIzoiAfkMMdzyVfQoHAw4Gr4M6CC4TGar118GhJS6GfR6HIopGDpzxmkS11nC4sXxoeaA77bAzWsJJ9W10Xnae4Vk2zIHUxUVJiGr62J1B45NhHp41A726WqJNaI7UbjRr1GkX0jChibFW6Chn1i3boIBpfVAf4Wa37sX4J9CjWrhG174rXixexFs9JAn3NVWGnWokWnCs1jfRI36xiIWfCXUj7bsbKeJtpxri2AzsskRJhUVzaNNA2iHR6iGHI0er34n6axnbrWis6o4H70VipGy7CH5fTqJakNI3MnuRvqbskBX8kXHpAbVNHN07ooGnrPrUCItRoRH1bco4VUVXrxHIoqM6ahzjGFh1h37ibpoXhX00b3iGaxG6XfVVeAVJoKfFVieI6zWrairpCRNRniVr0HWGKNWFRxTxRRGN1xBNXgrreeaNFWpz7637joijexGRAspXnRnQoU6bab4R7afC3C1k3NxiRX72kjARUGeMRMaR6k0wNxHj2kzHWH0XjtkrxJM0IhU4eaohWF8UCpCGjhXeAUse1piLGFl7x2J3VkVVnMr6UhR9nzUF473TNFXip35j3sR4nNws4hzU7p6IWWIR4Nf2Q3yFRf1RUz2sRhJG1aSxaffQAz7apoxIXJaX0nXa6Ffj3IkV0zxjUTVdkGUx", "K8dqDTE5Z5lgtvv9m9Qg8ugmYu9qDwaDgtKl5vylPLyLPLwlKETQ8v5YvTMwBKQKyT3Pl8tuKvmqgwEOQlx5vZLKgT5ABdw7yqPdZPmcuugDqOZwtNYgLcwBgTrEqlhKummLgmZDcHwcmm5LvmTvDLxlQyttK7DPgTucUq5DdlmKiSE8mBt93tOgTQKTGhCPBDudBLmgPtLvYTuydmcqD5EtEQZmwmmBLc5SEd89TyOlDYdwol8lDZl8cucOB9ggldm5QZPuPl58qttLQDP1TELyMtgggdutTuy9wZL8YwZqvw8EtgqqYK5LvK4yYwjBXSODNcDQHmEE8uvdZP9lQutwPcYyvQSwTLD8PcdgKE5DE89ZqdPBycc5wmQgLZT2B8ZE9wBzE58P9EOqYLTw5OUrSlTQPOqOTqtZBvwOv5yDwSddQY9BTqT8DY59BYQy9gPEl9gLZtEdvLuLByOB9S79DgrBtvZQqmyBr98y9tqc5cTcvP3mt9VE5mtEZuBaivBywYSO59YZEBgyISBYqBl8TZd8vSOETQZy8Qwl8g9BTvKBvS8LQSvYLqD9ZmYgTSQOdStmlqtTROYuOQDPuEuuS8gm5BlmPuEcZSydCc9tggu8cQmmXOxSTEvmBDKtd59LbqLlTPd9EcSKEwVIy58wgBDlwlQxTBTc5KmB8uZSqdjBLBYtmqlmGQKigTcdOmZKgOB9quvgcOWqBwuZmtw5KPZE9LlvtdluoS1SBRZuKQKlmtlsKgw85KuuOBqdKmYcgD8cQPtZLBvtugY5TrEqkvBTllqy5tEiuTZPvTPw7855L9diqEDyygCtmZ5BODKY8OuZSLEuwETZuLQqvTqODuKSy8qDvuRwqS8vEmYmEwmuQqEB8YcdAZEdovySPL8qOt1cKlc9ZluQEctPoLYYw9wOwgEqaZ9uLhuicQxKKEFYEzPc5y5tQdDm8qgODEOPBHDKcFwxTxYtdTBDEcE8yQgqQKggvrOtEjpEPcB9l5LDcPcQbDyyQyTDuwBBtDL5CqS5Ecdg3qTtDDuwmtBdEtLv0ulDOK8EKZiL8wuquS8Zqlmm85wyKSPQmv9uw99PKUQvPTumvdZ5gcLugv95PEcyl88wOtEQBQKZlyPgyY5cgvKvEBRDZcddww8lqSTP9LuPwlSdWymfZQEy2qPDQGvlyumDdSfQgmtOtBEmLvuYww7EKZTZEwumaBSmqP9ga83dTE9LlLEBBdugEvTSKYBDL8ugSy");
        System.out.println(s);
        for (int i=1;i<=10;i++){
            System.out.println(findTheWinner(i,3)+"---"+(findTheWinner(i,3)+3)%(i+1));
        }
        longestValidParentheses("()()))))()()(");
        new al().buildTree(new int[]{1,2,4,5,3},new int[]{4,2,5,1,3});*/
        //new al().minNumberDisappeared(new int[]{3,2,1});
        /*new al().solve(new int[][]{{1,2},{4,3}});
        new al().maxSlidingWindow2(new int[]{1,3,-1,-3,5,3,6,7},3);
        new al().maxWater(new int[]{4,5,1,3,2});
        MaxQueue maxQueue=new MaxQueue();
        maxQueue.offer(1);
        maxQueue.offer(10);
        System.out.println(maxQueue.max());
        maxQueue.offer(3);
        System.out.println(maxQueue.max());
        maxQueue.offer(9);
        System.out.println(maxQueue.max());
        System.out.println(maxQueue.poll());
        System.out.println(maxQueue.max());
        System.out.println(maxQueue.poll());
        System.out.println(maxQueue.max());*/
        /*String s= "[[\"a\",\"a\",\"b\",\"a\",\"a\",\"b\"],[\"b\",\"a\",\"b\",\"a\",\"b\",\"b\"],[\"b\",\"a\",\"b\",\"b\",\"b\",\"b\"],[\"a\",\"a\",\"b\",\"a\",\"b\",\"a\"],[\"b\",\"b\",\"a\",\"a\",\"a\",\"b\"],[\"b\",\"b\",\"b\",\"a\",\"b\",\"a\"]]";
        String replace = s.replace('[', '{');
        String replace1 = replace.replace(']', '}');
        replace1.replace("")
        System.out.println(replace1);
        /*System.out.println(replace1);
        new al().LFU(new int[][]{{1,1,1},{1,2,2},{1,3,3},{1,4,4},{2,4},{2,3},{2,2},{2,1},{1,5,5},{2,4}},4);
        System.out.println("abcd".substring(0,"abcd".length()-1));*/

    }



}
